如何恢复使用 jest.mock() 创建的模拟?

Ken*_*aka 15 unit-testing jestjs

显然,mock.mockRestore() 不会恢复使用 jest.mock() 创建的模拟的原始实现

// a.js
export default class A {}


// b.js
import A from './a';
export default class B extends A {}


// test.js
import A from './a';
import B from './b';

jest.mock('./a');
jest.mock('./b');

const b = new B();

test('instanceOf', () => {
    A.mockRestore();
    B.mockRestore();
    expect(b).toBeInstanceOf(A); // fails
});
Run Code Online (Sandbox Code Playgroud)

Bri*_*ams 19

mockFn.mockRestore仅适用于使用以下方法创建的模拟函数jest.spyOn

const obj = {
  func: () => 'original'
}

test('func', () => {
  const mock = jest.spyOn(obj, 'func');
  mock.mockReturnValue('mocked');

  expect(obj.func()).toBe('mocked');  // Success!

  mock.mockRestore();
  expect(obj.func()).toBe('original');  // Success!
})
Run Code Online (Sandbox Code Playgroud)

jest.spyOn包装原始函数并提供mockRestore作为恢复原始函数的方法。


jest.mock 调用的工作方式略有不同。

Jest接管require系统并jest.mock告诉Jest它应该在需要时返回模块模拟而不是实际模块。

这意味着模块模拟不会包装原始模块,它完全取代了require系统中的原始模块。所以mockRestore可以在模块 mock 中的 mock 函数上定义,但调用它不会恢复原始实现。


jest.mock 当您想为整个测试模拟整个模块时通常使用。

它在使用 ES6 样式的import语句时特别有用,因为babel-jesthoistsjest.mock调用并且它们在测试文件中的任何其他内容(包括任何import语句)之前运行:

import A from './a';  // <= A is already mocked...

jest.mock('./a');  // <= ...because this runs first

test('A', () => {
  // ...
}
Run Code Online (Sandbox Code Playgroud)

没有一种简单的方法可以在使用的测试期间恢复原始模块,jest.mock因为它的主要用途是模拟整个测试的模块。

如果您尝试在同一测试中同时使用模拟和原始实现,则有以下几种选择:

  • 使用模拟一个特定功能jest.spyOn并使用恢复它mockRestore
  • 使用jest.doMock以避免悬挂行为jest.mock...只是注意,您还需要使用require范围内使用jest.doMock,而不是使用顶级import
  • jest.requireAcutal随时使用require原模块

  • &gt; 使用 jest.mock 模拟的模块仅针对调用 jest.mock 的文件进行模拟。 (4认同)