【问题标题】:Jest mocks bleeding between tests, reset isn't fixing it开玩笑嘲笑测试之间流血,重置并没有解决它
【发布时间】:2021-11-30 11:55:14
【问题描述】:

测试两个模块,helper,它使用了renderrender 有可能抛出,所以我在 helper 中处理它,我想要测试以确保它按预期工作。

当我最初编写测试时,我使用jest.doMock 在测试本身中编写了该测试所需的内容,包括模拟。一旦所有测试通过,我想重构以尽可能共享模拟。

所以这段代码很好用:

test('throws', async () => {
    jest.doMock('./render', () => jest.fn(async () => { throw new Error('mock error'); }));

    const helper = require('./helper');

    expect(async () => { helper(); }).rejects.toThrow('mock error');
    expect(log_bug).toHaveBeenCalled();
});

test('succeeds', async () => {
    jest.doMock('./render', () => jest.fn(async () => 'rendered result'));

    const helper = require('./helper');

    expect(await helper()).toEqual(true); //helper uses rendered result but doesn't return it
    expect(log_bug).not.toHaveBeenCalled();
});

然而,这不是仅有的两个测试,到目前为止,大多数其他模拟渲染的测试都希望它返回其成功状态。我尝试将成功用例重构为__mocks__/render.js 中的一个文件,如下所示:

// __mocks__/render.js
module.exports = jest.fn(async () => 'rendered result');

然后将我的测试重构为这样,更干燥:

//intention: shared reusable "success" mock for render module
jest.mock('./render');

beforeEach(() => {
    jest.resetModules();
    jest.resetAllMocks();
});

test('throws', async () => {
    //intention: overwrite the "good" render mock with one that throws
    jest.doMock('./render', () => jest.fn(async () => { throw new Error('mock error'); }));

    const helper = require('./helper');

    expect(async () => { await helper(); }).rejects.toThrow('mock error');
    expect(log_bug).toHaveBeenCalled();
});

test('succeeds', async () => {
    //intention: go back to using the "good" render mock
    const helper = require('./helper');
    expect(await helper()).toEqual(true); //helper uses rendered result but doesn't return it
    expect(log_bug).not.toHaveBeenCalled();
});

有了这个更新的测试代码,错误记录测试仍然按预期工作——模拟被覆盖导致它抛出——但是对于下一个测试,错误再次抛出。

如果我颠倒这些测试的顺序以使模拟覆盖在最后,那么就不会发生失败,但这显然不是正确的答案。

我做错了什么?为什么在用doMock 覆盖后我的模拟无法正确重置? doMock docs 确实说明了我正在尝试做的事情,但它们没有显示将其与普通的手动模拟混合。

【问题讨论】:

    标签: javascript testing jestjs


    【解决方案1】:

    啊哈!我不断挖掘并找到this somewhat similar Q+A,这让我尝试了这种方法,而不是使用jest.doMock 覆盖测试内部:

    //for this one test, overwrite the default mock to throw instead of succeed
    const render = require('./render');
    render.mockImplementation(async () => {
        throw new Error('mock error');
    });
    

    有了这个,测试无论运行什么顺序都可以通过!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-20
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 1970-01-01
      • 2019-09-15
      • 2017-11-28
      相关资源
      最近更新 更多