在 Jest 测试中,使用 requireActual 不需要模块的实际版本

Gar*_*ary 7 javascript unit-testing mocking node.js jestjs

我有一个 Jest 测试文件,如下所示:

// utils.test.js
let utils = require('./utils')

jest.mock('./utils')

test('print items', () => {
  utils.printItems(['a'])
  expect(utils.getImage).toHaveBeenLastCalledWith('a.png')
})

test('get image', () => {
  utils = require.requireActual('./utils')

  // `utils` is still mocked here for some reason.
  expect(utils.getImage('note.png')).toBe('note')
})
Run Code Online (Sandbox Code Playgroud)

和这样的模拟:

// __mocks__/utils.js
const utils = require.requireActual('../utils');

utils.getImage = jest.fn(() => 'abc');

module.exports = utils;
Run Code Online (Sandbox Code Playgroud)

然而,正如您在第二次测试中的评论中看到的那样,utils仍然是模拟版本而不是模块的实际版本。这是为什么?我怎样才能让它成为实际版本,而不是模拟版本?

小智 4

在第二个测试中,您仍然会获得模拟的 utils 模块,因为您实际上在手动模拟 ( __mocks__/utils.js) 中需要它,而在 Jest 的缓存中,该模块仍然被引用为模拟,由于jest.mock()位于最顶层范围,因此应该返回该模拟。

修复它的方法是不在手动模拟中使用该模块,或者更新第二个测试以取消模拟并需要它的新版本。例如:

test('get image', () => {
  jest.unmock('./utils')
  jest.resetModules()
  const utils = require.requireActual('./utils')

  // `utils` is now the original version of that module
  expect(utils.getImage('note.png')).toBe('note')
})
Run Code Online (Sandbox Code Playgroud)

  • 我添加了 `jest.unmock('./utils')` 行(以及我已经拥有的其余代码),但不幸的是,它似乎没有改变任何东西。 (2认同)