As the title asks how do I test HTTP requests with Mocha and Chai?
I've recently started learning unit testing and I'm still getting confused with certain aspects of testing. I can get by fine testing methods that return a value but I'm confused on how to test methods that make HTTP/IO requests.
For example I have the following code:
module.exports = someRequest => new Promise((resolve, reject) =>
http.get('http://google.com', resp => {
if(resp.headers['content-type'] !== 200) {
reject(new Error('Failed to connect to Google'));
}
resolve('Connected to Google');
})
);
I want to test 2 cases:
Do I have to mock these requests and if so what's the purpose of mocking a method that is intended to make a HTTP request?
How about mocking http.get with something like that ?
const createHttpGetMock = (expectedStatus) => {
return httpGetMock = (address) => {
return new Promise((resolve, reject) => {
resolve({
status: expectedStatus,
headers: {
// ... headers
},
// mock response
})
})
}
}
Then your test could look like this :
describe("Google request", () => {
it("Resolves when google responds", async () => {
const httpSuccessMock = createHttpGetMock(200);
// Inject your mock inside your request function here, using your favorite lib
const message = await fetchGoogle();
assert.equals(message, 'Connected to Google');
})
it("Rejects when google responds with error", async () => {
const httpSuccessMock = createHttpGetMock(500);
// Inject your mock inside your request function here, using your favorite lib
const message = await fetchGoogle();
assert.equals(message, 'Failed to connect to Google');
})
});
This would fulfill the basic contract of a good unit test : regardless of external modules and dependencies, it ensures the module you're currently testing has the correct behaviour in each possible case.
Here is an example of test with mocha
and chai
. We also need sinon
to stub the http library.
http://sinonjs.org/releases/v1.17.7/stubs/
// test.js
const chai = require('chai');
const expect = chai.expect;
const sinon = require('sinon');
const http = require('http');
const someRequest = require('./index');
describe('some request test', function() {
let httpGetStub;
beforeEach(function() {
httpGetStub = sinon.stub(http, 'get'); // stub http so we can change the response
});
afterEach(function() {
httpGetStub.restore();
});
it('responses with success message', function() {
httpGetStub.yields({ headers: { 'content-type': 200 }}); // use yields for callback based function like http.get
return someRequest().then(res => {
expect(res).to.equal('Connected to Google');
});
});
it('rejects with error message', function() {
httpGetStub.yields({ headers: { 'content-type': 400 }});
return someRequest().catch(err => {
expect(err.message).to.equal('Failed to connect to Google');
});
});
})
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With