【问题标题】:Mocking npm package with different returns模拟具有不同回报的 npm 包
【发布时间】:2020-07-30 16:27:33
【问题描述】:

我正在尝试模拟一个 npm 包实现,既要返回解析为 true 的 Promise,又要返回另一个测试,我想以错误拒绝。

在测试文件的顶部,在第一个测试描述之前,我定义了以下代码来模拟一个 npm 包:

const mockNewFile = (): File => new File(['this is new file content'], 'new-file');
jest.mock('blueimp-load-image', () => () => {
    const newFile = mockNewFile();
    return new Promise(resolve => {
        const data = {
            image: {
                toBlob: (func: (file: File) => File) => {
                    func(newFile);
                }
            }
        };

        resolve(data);
    });
});

有了这个,我可以成功地为依赖于这个 npm 包的函数运行我的测试,称为 blueimp-load-image

但后来我想添加一个测试,看看如果这个 blueimp-load-image 函数失败会发生什么,也就是说,当它返回的承诺被拒绝时。

为此,我在测试文件的主要描述块中创建了一个新的描述块,并尝试在那里再次模拟 npm 包,让它返回一个不同的包:

describe('if loadImage returns an error', () => {
            beforeEach(() => {
                jest.mock('blueimp-load-image', () => () => {
                    return new Promise((resolve, reject) = reject(new Error('something went wrong')));
                });
            });

            test('return the file back unmodified', async () => {
                const expected = {/* file content */};
                const result = await theFunctionUsingLoadImage(file);

                expect(result).toStrictEqual(expected);
            });
        });

这里上面的测试失败了,因为似乎没有抛出任何错误,这导致我预计在 beforeEach 块中创建的模拟不起作用。我知道这一点是因为expectedresult 应该是相同的,只有在没有错误的情况下才会有所不同。

我也尝试使用 Jest.mock 的 jest.spyOn instado 来解决这个问题,但该尝试完全失败。

我错过了什么?

【问题讨论】:

    标签: javascript unit-testing npm jestjs


    【解决方案1】:

    Jest.mock 只能调用一次,并且应该实现模拟库的整个接口。

    有几种可能的选择:

    1. 使用mocks,它允许您编写一个可以公开其他(仅模拟)方法的模拟实现。
    2. jest.mock 与全局变量一起使用,该变量将控制模拟是返回成功还是拒绝。

    这是第二个选项的示例

    const mockNewFile = (): File => new File(['this is new file content'], 'new-file');
    let shouldSuccess = true;
    jest.mock('blueimp-load-image', () => () => {
        const newFile = mockNewFile();
        return new Promise((resolve, reject) => {
            if(!shouldSuccess) {
              return reject('data-of-reject');
            }
            const data = {
                image: {
                    toBlob: (func: (file: File) => File) => {
                        func(newFile);
                    }
                }
            };
    
            resolve(data);
        });
    });
    

    现在您需要做的就是将shouldSuccess 的值更改为false,以使您的模拟实现被拒绝。

    【讨论】:

    • 这行得通,也许不是模拟它的理想方法,但到目前为止我见过的最好的解决方案是用我的方式解决问题:)
    • 请注意,jest.mock 不允许任何超出范围的变量,除了一些例外。但是,如果shouldSuccessmock 为前缀,则可以使用。
    猜你喜欢
    • 2023-02-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2011-09-24
    • 1970-01-01
    相关资源
    最近更新 更多