【问题标题】:Is there a way to pass parameters to a mock function?有没有办法将参数传递给模拟函数?
【发布时间】:2018-12-12 22:49:51
【问题描述】:

使用 jest 进行单元测试,我有以下行:

jest.mock('../../requestBuilder');

在我的文件夹中,我有一个

__mocks__

我的模拟 requestBuilder.js 所在的子文件夹。我的笑话单元测试正确地调用了我的模拟 requestBuilder.js。问题是,我的 requestBuilder 正在模拟 ajax 返回,因此我希望能够确定是否应该返回成功或失败的服务器响应。理想情况下,我想将一个参数传递给我的模拟函数以确定是否“ajaxSuccess:true/false”。我怎样才能做到这一点?谢谢

【问题讨论】:

  • 请包含您当前的requestBuilder 模拟。

标签: javascript ajax unit-testing jestjs


【解决方案1】:

您不想将参数传递给模拟函数,传递给模拟函数的参数应该由您正在测试的代码段控制。您要做的是更改模拟函数执行之间的模拟行为。

假设您正在尝试测试这段 sn-p 代码:

// getStatus.js

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

module.exports = () => {
    try {
        const req = requestBuilder('http://fake.com/status').build();
        if (req.ajaxSuccess) {
            return {status: 'success'};
        } else {
            return {status: 'failure'}
        }
    } catch (e) {
        return {status: 'unknown'};
    }
};

我们要测试getStatus 是否正确使用requestBuilder,而不是测试builder.build() 方法是否正确工作。验证builder.build() 是单独的单元测试的责任。所以我们为我们的requestBuilder 创建一个模拟如下:

// __mocks__/requestBuilder.js

module.exports = jest.fn();

这个 mock 只是设置了 mock 函数,但它没有实现行为。模拟的行为应该在测试中定义。这将使您在逐个测试的基础上找到对模拟行为的粒度控制,而不是尝试实现支持每个用例的模拟(例如控制模拟行为的一些特殊参数)。

让我们使用这个新的模拟来实现一些测试:

// getStatus.spec.js

jest.mock('./requestBuilder');

const requestBuilder = require('./requestBuilder');
const getStatus = require('./getStatus');

describe('get status', () => {

    // Set up a mock builder before each test is run
    let builder;
    beforeEach(() => {
        builder = {
            addParam: jest.fn(),
            build: jest.fn()
        };
        requestBuilder.mockReturnValue(builder);
    });

    // every code path for get status calls request builder with a hard coded URL,
    // lets create an assertion for this method call that runs after each test execution.
    afterEach(() => {
        expect(requestBuilder).toHaveBeenCalledWith('http://fake.com/status');
    });

    it('when request builder creation throws error', () => {
        // Override the mocking behavior to throw an error
        requestBuilder.mockImplementation(() => {
            throw new Error('create error')
        });
        expect(getStatus()).toEqual({status: 'unknown'});
        expect(builder.build).not.toHaveBeenCalled();
    });

    it('when build throws an error', () => {
        // Set the mocking behavior to throw an error
        builder.build.mockImplementation(() => {
            throw new Error('build error')
        });
        expect(getStatus()).toEqual({status: 'unknown'});
        expect(builder.build).toHaveBeenCalled();
    });

    it('when request builder returns success', () => {
        // Set the mocking behavior to return ajaxSuccess value
        builder.build.mockReturnValue({ajaxSuccess: true});
        expect(getStatus()).toEqual({status: 'success'});
        expect(builder.build).toHaveBeenCalled();
    });

    it('when request builder returns failure', () => {
        // Set the mocking behavior to return ajaxSuccess value
        builder.build.mockReturnValue({ajaxSuccess: false});
        expect(getStatus()).toEqual({status: 'failure'});
        expect(builder.build).toHaveBeenCalled();
    });
});

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 1970-01-01
    • 2013-06-19
    • 2020-04-15
    • 2012-02-25
    相关资源
    最近更新 更多