Is there convenient way to mock the HTTP Request and Response objects for unit testing middlewares?
-
Is there a reason you don't include real HTTP requests in your test case? Should be reallx feasible in an async test setup.b_erb– b_erb2011-11-05 17:39:35 +00:00Commented Nov 5, 2011 at 17:39
-
12I went with that, but to be honest it does not feel like a unit test, it's more like integration one. Anyway, so far that is my best option.7elephant– 7elephant2011-11-05 17:41:34 +00:00Commented Nov 5, 2011 at 17:41
-
9I don't want to include real http requests because it makes my tests slower, and less reliable. For example, if one of the services I call is DB backed, and it fails because the DB in QA has been wiped out (or sync'ed with prod, or whatever) then my tests start failing. Also if you don't mock it's near impossible to reliably force certain error cases to happen. No, I like mocks--they make testing easier and more reliable.Kevin– Kevin2013-06-03 22:11:01 +00:00Commented Jun 3, 2013 at 22:11
9 Answers
It looks like both https://github.com/howardabrams/node-mocks-http and https://github.com/vojtajina/node-mocks can be used to create mock http.ServerRequest and http.ServerResponse objects.
2 Comments
From the tag, it looks like this question is about Express. In that case, supertest is very good:
var request = require('supertest')
, express = require('express');
var app = express();
app.get('/user', function(req, res){
res.send(201, { name: 'tobi' });
});
request(app)
.get('/user')
.expect('Content-Type', /json/)
.expect('Content-Length', '20')
.expect(201)
.end(function(err, res){
if (err) throw err;
});
For general Node use, Flatiron Nock looks like a good option:
var nock = require('nock');
var example = nock('http://example.com')
.get('/foo')
.reply(200, { foo: 'bar' });
var http = require('http');
var options = {
host: 'example.com',
port: 80,
path: '/foo',
method: 'GET'
}
var req = http.request(options, function(res) {
res.on('data', function(chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('error: ' + e);
});
req.end();
Output:
BODY: {"foo":"bar"}
1 Comment
request(app), seems to start a server (github.com/tj/supertest/blob/master/index.js#L20), and it is not mocking http reqeusts. Is that true?i'm using nodejutsu mock:
https://github.com/nodejitsu/mock-request
Maybe this is what you are looking for.
1 Comment
I wrote a library to mock out the responses of requests made via standard HTTP or via the request model:
Comments
Belatedly, if you're looking only to unit test the handler, you could inject express.Request and express.Response objects into the request function, or in this case, your middleware.
One that seemed to provide the minimal methods while keeping it simple was, for me, @jest-mock/express
If you're using supertest or nock, you're doing an integration test which can couple multiple tests. I'd also look into how it works internally because it is going be a pain to debug once it stops working.
it('should call next',
async () => {
const req = getMockReq({
headers: {
'user-agent': 'Chrome',
},
path: '/path',
})
const{res, next, clearMockRes} = getMockRes({})
await middleware(req, res, next)
expect(res.send).not.toHaveBeenCalledWith()
expect(next).toHaveBeenCalled()
})
Comments
Check out https://github.com/timsavery/node-hmock or npm install hmock...any feedback welcome! The solution has worked well for me thus far.
Comments
Mockery looks great for this.
Essentially it hijacks require calls, and returns a different object/function stub that you specify.
Comments
I do not recommend this solution for real world usage, but this is the hack I used just to avoid exceptions in an experiment.
const mock_response_obj = {
statusCode: null,
setHeader: () => {},
writeHead: () => {},
end: () => {},
}
Obviously extend it as needed. Sharing in case anyone else is looking for a simple stopgap.