Performing a real HTTP request in a unit test can make it slow and brittle, so the solution is to mock the Node HTTP library. This guide will show you how to create mock objects that simulate successful and unsuccessful HTTP requests.
Mocking the ‘http’/’https’ Library
If you are using dependency injection and passing the http
object into your class then this is simple: create a new object and implement the methods you use via JEST’s jest.fn()
function.
test('Test an HTTP request with dependency injection', async () => {
const http = {
get: jest.fn(...),
};
// Call the function under test and check the expected result.
const result = functionUnderTest(http);
expect(result).toBe(true);
}
If you are not using dependency injection then you can use jest.mock()
to override it globally:
test('Test an HTTP request without dependency injection', async () => {
const mock = {
get: jest.fn(...),
};
jest.mock('http', () => mock);
// Call the function under test and check the expected result.
const result = functionUnderTest();
expect(result).toBe(true);
}
Mocking the Request and Response
When http.get()
is called it must return an http.Request
object. This will then return an http.Response
object in the response
event handler. You must respond to these events by returning mock objects. These objects should extend EventEmitter
. Note that the callback parameter to the http.get()
function is bound to the request
event on the request object.
test('Test an HTTP request with dependency injection', async () => {
const request = new EventEmitter();
const http = {
get: jest.fn((url, options, callback) => { request.on('request', callback); return request; }),
};
const response = new EventEmitter();
response.statusCode = 200;
// The response starts by emitting a 'request' event.
request.emit('request', response);
// The response body is returned in the 'data' event, followed by 'end'.
response.emit('data', 'page contents');
response.emit('end');
// Indicate that no more responses will be sent.
request.emit('close');
// Call the function under test and check the expected result.
const result = functionUnderTest(http);
expect(result).toBe(true);
}