开玩笑:如何计算通过`call`或`apply`调用的模拟方法的调用?

时间:2019-03-03 14:04:46

标签: javascript unit-testing mocking jestjs

如何使用模拟来计算通过callapply进行的函数调用

// mylib.js
module.exports = {
  requestInfo: function(model, id) {
    return `The information for ${model} with ID ${id} is foobar`;
  },
  execute: function(name) {
    return this[name] && this[name].apply(this, [].slice.call(arguments, 1));
  },
};
// mylib.test.js
jest.mock('./mylib.js');

var myLib = require('./mylib.js');

test('', () => {
  myLib.execute('requestInfo', 'Ferrari', '14523');
  expect(myLib.execute.mock.calls.length).toBe(1); // Success!
  expect(myLib.requestInfo.mock.calls.length).toBe(1); // FAIL
});

如果我明确呼叫myLib.requestInfo,则第二个期望成功。

是否有办法监视通过applycall调用了函数的模块模拟​​调用?

1 个答案:

答案 0 :(得分:2)

来自jest.mock doc

  

在需要时使用自动模拟的版本对模块进行模拟。

可以通过更好地描述“自动模拟版本”的含义来改进文档,但是发生的事情是Jest保持模块的API表面相同,同时用空的{{ 3}}。


因此,在这种情况下,execute被调用,但是它已被空的模拟函数代替,因此requestInfo从未被调用,这会导致测试失败。


要使execute的实现保持完整,您将要避免自动模拟整个模块,而是使用mock functions之类的东西监视原始功能:

var myLib = require('./mylib.js');

test('', () => {
  jest.spyOn(myLib, 'execute');  // spy on execute
  jest.spyOn(myLib, 'requestInfo')  // spy on requestInfo...
    .mockImplementation(() => {});  // ...and optionally replace the implementation
  myLib.execute('requestInfo', 'Ferrari', '14523');
  expect(myLib.execute.mock.calls.length).toBe(1); // SUCCESS
  expect(myLib.requestInfo.mock.calls.length).toBe(1); // SUCCESS
});