【问题标题】:Difference between resetAllMocks, resetModules, resetModuleRegistry, restoreAllMocks in JestJest 中的 resetAllMocks、resetModules、resetModuleRegistry、restoreAllMocks 之间的区别
【发布时间】:2020-01-28 18:02:39
【问题描述】:

我正试图用 Jest 来理解以下内容:

resetAllMocksresetModulesresetModuleRegistryrestoreAllMocks

我觉得很难。

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

【问题讨论】:

    标签: javascript unit-testing mocking jestjs


    【解决方案1】:

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

    fn 的引用暗示了每个操作下的示例笑话模拟函数。

    jest.clearAllMocks()clearMocks:[boolean]

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

    jest.resetAllMocks()resetMocks:[boolean]

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

    jest.restoreAllMocks()restoreMocks:[boolean]

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

    因此,如果我们使用 jest.fn()(不是间谍)手动分配事物,我们必须自己处理实现恢复,因为 jest 不会这样做。

    jest.resetModules()resetModules:[boolean]

    它会重置 Jest 的模块注册表,该注册表是所有必需/导入模块的缓存。调用 this 后,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')
          })
        })
      })
    })
    

    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)
    

    【讨论】:

    • 我认为你的第二个“resetMocks:[boolean]”应该有“restore”而不是“reset”。
    • @HewWolff 已更正。谢谢。
    【解决方案2】:

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

    快速提示:

    1. 如果你想测试模拟函数调用次数,使用前clear
    2. 如果您想确保模拟返回值不会污染其他测试用例,请致电reset
    3. 如果您想使用 origin 方法而不是 mock 实现,请调用 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);
        });
    });
    

    【讨论】:

    猜你喜欢
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 2021-12-25
    • 2020-05-10
    • 2014-09-20
    • 2010-10-28
    • 2015-10-04
    相关资源
    最近更新 更多