Stubing 来自另一个函数的 class 调用

Stubing a class call from another function

我有 2 个文件 controller.js 和 entity.js,它们相互交互。我正在测试 controller.js,它会创建一个 entity.js (class) 的实例并使用它的一个函数。我怎样才能 stub/mock/spy 那个方法的调用和 return?

controller.js

const controller= async (req, res) => {

try {
    ...

    const entity = new Entity({
    ...
    });

    const validation = await entity.validate();

    ...
    return res.send()
    }
  } catch (error) {
    return res.send(error)
  }
};

Entity.js

class Entity{
  constructor() {
  ...
  }

  ...

  async validate() {
    ...
    return response;
  }
}

知道如何使用 supertest、sinon 和 chai 测试 controller.js 吗?

Sinon 会愉快地存根该函数。因为它是一个 class 方法,你只需要确保在原型上存根函数:

const controller = async (req, res) => {
      const entity = new Entity();
      const validation = await entity.validate();
      console.log(validation)
  };
  
class Entity{
    constructor() {}
    async validate() {
      return "real function";
    }
}
// stub it
let stub = sinon.stub(Entity.prototype, 'validate')
stub.returns('stubbed function')

controller()
<script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/7.1.1/sinon.min.js"></script>

此解决方案使用 Ava(但您应该能够轻松适应 Mocha)。但是我更熟悉testdouble。如果你在 sinon 上没有成功(我相信你会的),这里有一个你可能想要考虑的替代方案。

所以如果我们有 burrito.js:

module.exports = class {
   eat() {
      return '';
   }
};

lunch.js

var Burrito = require('./burrito');
module.exports = () => (new Burrito()).eat();

那么在你的测试中:

const td = require('testdouble');
const test = require('ava');

test('swap burrito', t => {

  td.replace('./burrito', class FakeBurrito  {
    eat() {
      return '';
    }
  });

  const lunch = require('./lunch');

  t.is(lunch(), ''); // PASS
  t.is(lunch(), ''); // FAIL
});

关键是在你的被测对象(你的午餐)需要它之前要求你的依赖(墨西哥卷饼),这样你就有时间伪造它。