Jest中resetAllMocks、resetModules、resetModuleRegistry、restoreAllMocks的区别

tmp*_*dev 43 javascript unit-testing mocking jestjs

我试图在 Jest 中围绕以下内容:

resetAllMocks, resetModules,resetModuleRegistryrestoreAllMocks

我发现这很难。

我阅读了 jest 文档,但不太清楚。如果有人可以向我提供上述工作方式的示例,并且它们彼此不同,我将不胜感激。

sep*_*ehr 72

以下部分解释了每个函数的行为及其相应的配置指令。在 config 指令的情况下,解释的行为发生在每个测试之间,使它们越来越与其他测试隔离。

fn对这些操作的引用暗示了每个操作下的示例玩笑模拟功能。

jest.clearAllMocks()clearMocks:[boolean]

重置所有模拟使用数据,而不是它们的实现。换句话说,它只替换了 jest 模拟函数的fn.mock.callsfn.mock.instances属性。

jest.resetAllMocks()resetMocks:[boolean]

它的超集clearAllMocks()还负责将实现重置为no return函数。换句话说,它将用 new 替换模拟函数jest.fn(),而不仅仅是它的fn.mock.callsand fn.mock.instances

jest.restoreAllMocks()restoreMocks:[boolean]

与 类似resetAllMocks(),但有一个非常重要的区别。它恢复了“间谍”的原始实现。所以,它就像“用 jest.fn() 替换模拟,但用它们的原始实现替换间谍”

因此,在我们使用 jest.fn()(不是间谍)手动分配东西的情况下,我们必须自己处理实现恢复,因为 jest 不会这样做。

jest.resetModules()resetModules:[boolean]

它重置 Jest 的模块注册表,它是所有必需/导入模块的缓存。Jest 将在调用后重新导入任何需要的模块。想象一个干净的石板,而不必处理其他测试中的所有模拟模块。

jest.resetModuleRegistry

它只是 的别名resetModules,请参阅:https :
//github.com/facebook/jest/blob/7f69176c/packages/jest-runtime/src/index.ts#L1147


了解清除、重置和恢复的不同之处:https :
//repl.it/@sepehr/jest-mock-api-reset-restore#jest-mock-apis.test.js

describe('jest mock reset/restore api', () => {
  
  describe('when calling mockReset() on a test double with custom impl.', () => {
    describe('if the test double is a spy', () => {
      test('jest replaces the impl. to a new undefined-returning jest.fn()', () => {
        const module = { api: () => 'actual' }
        jest.spyOn(module, 'api').mockImplementation(() => 'spy mocked')
        
        expect(module.api()).toStrictEqual('spy mocked')
        expect(module.api).toHaveBeenCalledTimes(1)

        module.api.mockReset()

        expect(module.api()).toStrictEqual(undefined)
        expect(module.api).toHaveBeenCalledTimes(1)
      })
    })
    

    describe('if the test double is "not" a spy', () => {
      test('jest replaces the impl. to a new undefined-returning jest.fn()', () => {
        const api = jest.fn(() => 'non-spy mocked')
        
        expect(api()).toStrictEqual('non-spy mocked')
        expect(api).toHaveBeenCalledTimes(1)

        api.mockReset()

        expect(api()).toStrictEqual(undefined)
        expect(api).toHaveBeenCalledTimes(1)
      })
    })
  })

  describe('when calling mockRestore() on a test double with custom impl.', () => {
    describe('if the test double is "not" a spy', () => {
      test('jest resets the impl. to a new undefined-returning jest.fn()', () => {
        const api = jest.fn(() => 'non-spy mocked')
        
        expect(api()).toStrictEqual('non-spy mocked')
        expect(api).toHaveBeenCalledTimes(1)

        api.mockRestore()

        expect(api()).toStrictEqual(undefined)
        expect(api).toHaveBeenCalledTimes(1)
      })
    })

    describe('if the test double is a spy', () => {
      test('jest restores the original impl. of that spy', () => {
        const module = { api: () => 'actual' }
        jest.spyOn(module, 'api').mockImplementation(() => 'spy mocked')
        
        expect(module.api()).toStrictEqual('spy mocked')
        expect(module.api).toHaveBeenCalledTimes(1)

        module.api.mockRestore()

        expect(module.api()).toStrictEqual('actual')
        expect(module.api).not.toHaveProperty('mock')
      })
    })
  })
})
Run Code Online (Sandbox Code Playgroud)
PASS  ./jest-mock-apis.test.js

jest mock reset/restore api
  when calling mockReset() on a test double with custom impl.
    if the test double is a spy
      ? jest replaces the impl. to a new undefined-returning jest.fn() (18ms)
    if the test double is "not" a spy
      ? jest replaces the impl. to a new undefined-returning jest.fn() (17ms)

  when calling mockRestore() on a test double with custom impl.
    if the test double is "not" a spy
      ? jest resets the impl. to a new undefined-returning jest.fn() (2ms)
    if the test double is a spy
      ? jest restores the original impl. of that spy (7ms)
Run Code Online (Sandbox Code Playgroud)

  • 我认为你的第二个“resetMocks:[boolean]”应该有“恢复”而不是“重置”。 (2认同)

鄭元傑*_*鄭元傑 14

感谢@sepehr 的回答。
我认为通过示例会更容易理解。

快速提示:

  1. 如果要测试模拟函数调用次数,请clear在使用之前
  2. 如果您想确保模拟返回值不会污染其他测试用例,请调用 reset
  3. 如果要使用 origin 方法而不是模拟实现,请调用restore.
import {Calculator} from './calculator';

describe('calculator add', function () {
    let calculator = new Calculator();
    const mockAdd = jest.spyOn(calculator, 'add');
    it('mock the add method', function () {
        calculator.add = mockAdd.mockReturnValue(5);
        expect(calculator.add(1, 2)).toBe(5);
    });

    it('because we didnt clear mock, the call times is 2', function () {
        expect(calculator.add(1, 2)).toBe(5);
        expect(mockAdd).toHaveBeenCalledTimes(2);
    });

    it('After clear, now call times should be 1', function () {
        jest.clearAllMocks();
        expect(calculator.add(1, 2)).toBe(5);
        expect(mockAdd).toHaveBeenCalledTimes(1);
    });

    it('we reset mock, it means the mock has no return. The value would be undefined', function () {
        jest.resetAllMocks();
        expect(calculator.add(1, 2)).toBe(undefined);
    });

    it('we restore the mock to original method, so it should work as normal add.', function () {
        jest.restoreAllMocks();
        expect(calculator.add(1, 2)).toBe(3);
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 我没有测试过。但根据这个SO,我们不需要。/sf/ask/3089889351/ Between-test-modules (2认同)