It's important to remember that when using a mock function, you shouldn't pass parameters into it. The parameters should be controlled by the code being tested. Instead, focus on changing the behavior of the mock function for different executions.
For example, let's say we have the following code snippet to test:
// 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'};
}
};
The goal is to test that getStatus
correctly uses requestBuilder
, not whether builder.build()
works properly. The testing of builder.build()
belongs in a separate unit test. To create a mock for requestBuilder
, use the following:
// __mocks__/requestBuilder.js
module.exports = jest.fn();
This sets up the mock function without implementing its behavior. The behavior of the mock should be defined in the test itself. This approach allows for precise control over mocking behavior on a per-test basis, rather than trying to cover every possible scenario with one generic mock.
Now, let's write some tests using this new 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
let builder;
beforeEach(() => {
builder = {
addParam: jest.fn(),
build: jest.fn()
};
requestBuilder.mockReturnValue(builder);
});
// Assert that request builder is called with specified URL after each test
afterEach(() => {
expect(requestBuilder).toHaveBeenCalledWith('http://fake.com/status');
});
it('handles error during request builder creation', () => {
// Override mock behavior to throw an error
requestBuilder.mockImplementation(() => {
throw new Error('create error')
});
expect(getStatus()).toEqual({status: 'unknown'});
expect(builder.build).not.toHaveBeenCalled();
});
it('handles error during build', () => {
// Simulate build error in mock behavior
builder.build.mockImplementation(() => {
throw new Error('build error')
});
expect(getStatus()).toEqual({status: 'unknown'});
expect(builder.build).toHaveBeenCalled();
});
it('handles successful response from request builder', () => {
// Simulate successful response from request builder
builder.build.mockReturnValue({ajaxSuccess: true});
expect(getStatus()).toEqual({status: 'success'});
expect(builder.build).toHaveBeenCalled();
});
it('handles failure response from request builder', () => {
// Simulate failure response from request builder
builder.build.mockReturnValue({ajaxSuccess: false});
expect(getStatus()).toEqual({status: 'failure'});
expect(builder.build).toHaveBeenCalled();
});
});