jest.spyOn相当于jest.mock

时间:2019-01-23 02:40:31

标签: javascript mocking jestjs spy

模拟整个模块,但保留原始模块逻辑。与jest.spyOn默认行为类似,在默认行为中调用了原始方法。

使用jest.mock可以执行所需的断言,但不执行原始逻辑,有时我希望执行该逻辑。 使用jest.spyOn可以声明并可以执行原始逻辑,但只能在模块的命名导出上使用,这通常是有用的,但在默认情况下或在下面的示例代码中将方法导出时则无效。

// moduleToMock.js
function doSomething(..args) {...}

doSomething.myWay = function myWay(...args) {...}

module.exports = doSomething

// moduleUsingModuleToMock.js
const doSomething = require('moduleToMock')

function doManyThings() {
    doSomething(...)
    doSomething.myWay(...)
}

module.exports = {
    doManyThings,
}

// moduleUsingModuleToMock.test.js
// --
// some way to mock `moduleToMock` that still executes original logic
// --
const doSomething = require('moduleUsingModuleToMock')
it('correctly does many things', () => {
    doManyThings()
    expect(doSomething).toBeCalledWith(...)
    expect(doSomething.myWay).toBeCalledWith(...)
})

也许我错过了一些简单的事情,但是到目前为止,文档或Google Fu都没有产生任何结果。

3 个答案:

答案 0 :(得分:1)

我目前正在这样

jest.mock('./somepath', () => (
  Object.fromEntries(
    Object.entries(jest.requireActual('./somepath'))
      .map(([key, value]) => [key, jest.fn(value)])
  )
))

这使模块保留了原始实现,但是由于所有导出都封装在jest.fn中,因此现在可以在每个特定测试中使用不同的实现来模拟它们

答案 1 :(得分:0)

无法模拟模块并监视其方法。原因是玩笑真的用模拟代替了模块。

答案 2 :(得分:0)

这种情况经常发生,以至于我决定编写自己的库来生成自动模拟模块的模块,这些模块保留原始实现,但可以像jest.spyOn一样被覆盖。

Jest Mock Module

import * as mock from "jest-mock-module";
mock.extend(jest); // optionally extend jest to use the "jest.spy" syntax
jest.spy("src/moduleToMock"); // Placed before other imports like "jest.mock".

import moduleToMock from "src/moduleToMock";
import moduleToTest from "src/moduleToTest";

it("does a thing", () => {
  moduleToTest.callFunctionThatUsesModuleToMock();
  expect(moduleToMock.usedFunction).toHaveBeenCalledTimes(1);
});