您不想将参数传递给模拟函数,传递给模拟函数的参数应该由您正在测试的代码段控制。您要做的是更改模拟函数执行之间的模拟行为。
假设您正在尝试测试这段 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();
});
});