How to Mock HTTP Request and Response

The depth of an HTTP request or response mock brings a level of complexity to the whole system. In this article, we revisit some techniques used to mock HTTP request/response when used in the same test case.

In this article we will talk about:

Even though this blog post was designed to offer complementary materials to those who bought my Testing nodejs Applications book, the content can help any software developer to tuneup working environment. You use this link to buy the book. Testing nodejs Applications Book Cover

Show me the code

module.exports.getUsers = function getUsers(req, res, next){
  UserModel.find(req.params, (error, users){
    if(error) return next(error, null);
    return res.status(200).json(users);
  });
}

Example: in controller/get-users.js

What can possibly go wrong?

When trying to figure out how to approach mocking request and response objects, the following points may be a challenge:

How to mock Request/Response Objects the easy way

Testing an expressjs middleware provides a good use case where mocking a request and response in the same test case makes sense.

Key objectives are:

var sinon = require('sinon'),
    chai = require('chai'),
    expect = chai.expect,
    getUsers = require('./controller').getUsers;

describe("getUsers()", function() {
  it("should guarantee a response", function() {
    var req  = {}, 
      res  = { send: sinon.spy()}, 
      next = sinon.spy();
    getUsers(req, res, next);
    expect(res.send.calledOnce).to.equal(true);
    res.send.restore(); 
  });     
});

code excerpt adapted from – Unit Testing Controllers the Easy Way in Express 4

Particular Case: How to mock a response that uses a streaming, or other hard to mock interfaces. Keyword: let the flow intact, but fake read/write data instead.

Mocking request

Request object provided by node-mocks-http is pretty similar to the request provided by the native http found in nodejs library

var request;
//When method = GET|DELETE
request = httpMock.createRequest({method: method, url: url});

//When method = PUT|POST
var request = httpMock.createRequest({method, url, body: body})

Mocking Response

//initialization(or beforeEach)
var response = httpMock.createResponse({
    eventEmitter: require('events').EventEmitter
});

//Usage: somewhere in tests
let next = sinon.spy();
getUsers(request, response, next);
response.on('end|data|error', function(error){
  //write tests in this close.
});

Using node-mocks-http is in the gray area of integration testing. However, this technique can be verifiable in use cases where the first strategy falls short.

There is more on integration testing mocking strategy: How to Mock HTTP Request and Response ~ Integration testing use case

Conclusion

In this article, we revisited strategies to mock HTTP Request and Response methods in the same test case, while using mock data to emulate interaction with remote systems. We also re-iterated the difference between stubbing and mocking, and how spies(fake) fall into the testing big picture. There are additional complimentary materials in the “Testing nodejs applications” book on this very same subject.

References

#snippets #http #request #response #mocking #stubbing