eugef / node-mocks-http Goto Github PK
View Code? Open in Web Editor NEWMock 'http' objects for testing Express routing functions
License: Other
Mock 'http' objects for testing Express routing functions
License: Other
I suggest we add the Express res.type()
method to mockResponse
as described in http://expressjs.com/4x/api.html#res.type.
Tried following instructions and samples - to no avail - the response object never fires an event. Not end
, not send
.
Here's a simple function (using Express 4.*):
export function getServiceHealth(req, res) {
let message = 'service has been up for ' + process.uptime() + ' seconds!';
res.status(200).send(message);
}
And here's my test. It times out.
import {EventEmitter} from 'events';
import httpMock from 'node-mocks-http';
import {getServiceHealth} from '../../lib/controllers/health/';
describe('Service health integration tests', () => {
it('should get health', done => {
let req = httpMock.createRequest({url: '/health'});
let res = httpMock.createResponse({EventEmitter: EventEmitter});
getServiceHealth(req, res);
res.on('end', () => {
console.log(res._getData());
done();
});
res.on('send', () => {
console.log(res._getData());
done();
});
//setTimeout(() => {console.log(res._getData()); done();}, 1000);
});
});
I resorted to the commented line at the end, that fires done()
using setTimeout. Obviously, not the right way to go. What do I have to do to get the event triggered on res
?
(BTW, when I log res
it gets the right status and data)
Note: on the off chance that this is some ES6 import
shenanigan, I tried this:
let res = httpMock.createResponse({EventEmitter: require('events').EventEmitter});
Same result.
@howardabrams, as per your comment on PR #36, I understand the intent of your project is to maintain compatibility between both the Node and Express APIs. (Thanks again for sharing ... this is an awesome mock).
That being the case, it should be noted that Node's http.ServerResponse
class initializes the statusCode
property to 200
(see code here). This means that mockResponse.statusCode
should likewise default to 200
(instead of -1
).
Since Express extends Node's http.ServerResponse
class (see code here), the status code of its response object will also default to 200
Changing the default statusCode
in mockResponse
to 200
will make that behavior consistent with both Node and Express.
I understand this will be a "breaking" change, but in the interest of maintaining compatibility with both Node and Express I think issue should be addressed. I will submit a PR for your consideration later today.
npm shows current version is 1.5.3 but github shows only 1.4.3
How is github so far behind? Are tags not getting pushed? Commits missing on github?
mockResponse.send()
should call .end()
response.send()
calls .end()
.end()
is not never called ._isEndCalled()
returns false
after calls to .send()
req.res should exist, as should res.req.
I'm not sure if there should be a single api method that creates both req and res under the hood (and returns both as array? or object? or just one or the other?)
Or if the createRequest/createResponse methods should accept the other half of the pair and do the wireup?
Or if there should be a separate utility method that just accepts already-created req/res mocks and associates them.
Thoughts?
I'd be happy to work on the PR, once a direction is decided that fits the goals of the project.
response
objects throw a circular reference error when passed to JSON.stringify
whereas these mock response objects do not. For better fidelity to the objects they're mocking it'd be good to replicate teh circular references responses contain (I haven't looked into this in too much depth yet - it may only apply to express response objects)
Can i use node-mocks-http for testing async? for eg: I have this in my router which can be reached through GET /category/list
var getData = function (req, res) {
MongooseCategory.find({}, function (err, docs) {
if (!err) {
res.json(200, { categories: docs });
} else {
res.json(500, { message: err });
}
});
};
In the test
var response = httpMocks.createResponse();
getData(request, response);
console.log(response._getData());
but the response does not contain the json (response comes back later after a few seconds). How can i test this? Any help is much appreciated.
Hello,
I came across this library and was wondering can it be used to provide a mock response when a request is made?
I have been looking at nock which allows for this, but couldn't see anything similar with this library, unless I have misunderstood the docs.
Thanks
Express 4.8.x ++ supports .sendFile
to send a file from the filesystem ( docs ). Looks like that's not supported currently on the return from createResponse
.
According to Express:
The
Referrer
header field is special-cased, bothReferrer
andReferer
are interchangeable.
mockRequest.header()
does not currently handle this edge-case.
The mockResponse.js
does not have a header
, set
, or get
method, which Express does have.
http://expressjs.com/4x/api.html#res.set
http://expressjs.com/4x/api.html#res.get
I will add these and make them aliases of the setHeader
and getHeader
methods and submit a pull request soon.
node-mocks-http is now on feature freeze, as we prepare for our 2.0
release.
If necessary we will create 1.4.x
bug fix releases, but no new features will be implemented in the 1.x branch.
Please see issue #54, to track the progress of our 2.0
release.
Currently, redirect() without a statusCode will leave the statusCode as -1. However, a redirect will, in practice, default to a 302.
The following mocha code will timeout instead of displaying the assertion error:
it('tests things', function(done){
var response = httpMocks.createResponse({eventEmitter: require('events').EventEmitter});
var request = httpMocks.createRequest({
method: 'GET',
url: '/'
});
response.on('end', function() {
[].should.have.length(2);
done();
});
subject.handle(request, response);
});
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
If I set it to validate against length 0, the test passes fine.
PR #30, more specifically commit 6f43349, introduced an error on line 31 of mockRequest.js.
Running the tests throws the following error:
assert.js:93
throw new assert.AssertionError({
^
AssertionError: path must be a string
at Module.require (module.js:362:3)
at require (module.js:380:17)
at Object.<anonymous> (/Users/johnnyestilles/Projects/node-mocks-http/lib/mockRequest.js:31:11)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/Users/johnnyestilles/Projects/node-mocks-http/lib/http-mock.js:8:16)
I assume the line should read ...
var url = require('url');
instead of ...
var url = require(url);
Could you make the Typescript definitions file (*.d.ts) of this module?
https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html
It's a great tool for writing in TS or JS because it provide intellisens, code completion, error checking before compilation and other amazing stuffs which makes developer life much easier ;)
When testing an http handler outside Express, there is no body
field containing the POST body, instead the request has to be handled as a stream and parsed accordingly, e.g. using the formidable module. For that to work, the mock request has to be an event emitter and would need to expose a method for sending the post body, which then triggers the right data
and end
events.
I've hacked this together locally - if there's interest in supporting this, I can look into putting together a PR.
The message shown when No match for the request was found
should include the server port evidencing that it was correctly set. Consider the example below:
var scope = nock('http://localhost:8003')
.get('/employees/')
.reply(200, {});
var http = require('http');
var opt = {
hostname: 'localhost',
port: "8003",
path: '/employees/?status=ALL',
method: 'GET'
};
var req = http.request(opt, function(res) {
...
});
req.on('error', function(e) {
...
});
req.end();
Nock: No match for request GET http://localhost/employees/?status=ALL
The error message suggests that the the server port was not set in the request. It took me some time to realize that the problem was not the server port but the query string that was missing. It would be easier to identify the problem if the port were also in the error message.
Nock: No match for request GET http://localhost:8003/employees/?status=ALL
The example in the readme assumes that the response is sync. Since I'm testing a wrapper around an actual http API, the response is async, so I need an event or callback. Neither "end" nor "close" seem to get emitted, and I don't think I'm missing something, since the end method doesn't bother.
I can provide a patch, but would like to get confirmation that it would get merged etc.
please?
We want node-mocks-http
to provide Express 4.x
compatible request
and response
object mocks. As with 1.x
we want 2.x
to be as lightweight and dependency free as possible.
The list below is a first draft of our roadmap towards 2.0
. It is by no means comprehensive or final. Comments, questions and requests are most definitely welcome.
mockStream
(with sufficient functionality for mockStreamReadable
), which will inherit from EventEmitter
Stream
mockEventEmitter
in favor using a real EventEmitter
mockStreamReadable
(with sufficient functionality for mockHttpIncomingMessage
), which will inherit from mockStream
Stream.Readable
mockStreamWritable
(with sufficient functionality for mockHttpOutgoingMessage
), which will inherit from mockStream
Stream.Writable
mockHttpIncomingMessage
node/_http_incoming.js
(to mock http.IncomingMessage
), which will inherit from mockStreamReadable
mockHttpOutgoingMessage
(to mock http.OutgoingMessage
), which will inherit from mockWritableReadable
mockHttpServerResponse
(to mock http.ServerResponse
)mockApp
, which will serve as a parent to mockRequest
and mockResponse
, and will perform some initialization task, so as associating mockRequest
with mockResponse
(and vice versa). It will likewise provide the ability to configure Express-related settings that have an effect on request
and response
.createRequest()
and .createResponse()
methods in favor of a .createApp()
, which will return an mockApp
instance that includes both a mockRequest
and a mockResponse
instance.NOTE: The intent of the above mocks is to support (via inheritance)
mockRequest
andmockResponse
. These will contain only a subset of their "real life" counterparts. They will be used internally bynode-mocks-http
and will not be exported for consumption.We will consider expanding them to full-blown mocks that can be made available for public consumption in future versions of
node-mocks-http
.
mockRequest
to inherit from mockHttpIncomingMessage
mockResponse
to inherit form mockHttpServerResponse
The proposed changes for 2.0
will either response or provide a means to resolve all pending issues.
If you're a node-mocks-http
user/consumer we would love to hear your thoughts regarding our 2.0 Roadmap. Please leave your comments below.
For those of you who wish to contribute, we will be creating we've merged our progress of 2.x
branch during the first week of April against which you can submit your pull requests.2.x
onto master
. Submit any pull request for 2.x
against master
. Please read and follow our contributing guidelines prior to your submission.
According to the Express docs calling res.send({foo: 'bar'})
is identical to calling res.json({foo: 'bar'})
. However in the mock response, these are handled differently with only json
setting the content type header and stringifying the data.
I'm writing some tests for my sessions handling and have found two minor problems.
In express 3, sessions throws an error if req.signedCookies is not set.
var unsignedCookie = req.signedCookies[key];
This seems to have been fixed in express 4, but that's based on reading the code, not trying it...
.
Second, mockRequest.session is set to {} by default but the session isn't created if req.session is truthy
return function session(req, res, next) {
// self-awareness
if (req.session) return next();
The mockRequest value is set by this:
mockRequest.session = (options.session) ? options.session : {};
So any falsey option gets the default value, so I can't do { session : null }.
As a side note, mockRequest({ body : 0 }) will result in req.body = {}.
Workarounds simply
var req = httpMocks.createRequest({});
req.signedCookies = {}
delete req.session
Would it be useful to ignore the case of response headers? For example, have res.getHeader return the value regardless of being passed "content-type" or "Content-Type"?
My node controller parses a url form the request using the below form:
req.protocol + '://' + req.get('host') + req.originalUrl;
In order to test this, I need to send a request with the above properties, in particular the get
function is required (req.originalUrl
will be undefined
, but req.get(...)
will throw an error).
However, this mock library doesn't allow for the user to add these 'custom' options to the request. That feature should be added.
When a client calls http.request with a path but no URL, the server receives a Request object containing a URL but no path.
As I understand the aims of this project, we should try to mimic this behaviour. I.e. createRequest should auto-populate the URL property in a similar manner.
res.format
is super useful for having an endpoint that handles multiple Accept headers. Without this, these endpoints can't be tested.
Hey!
Could you add support for Writable Stream? It can be used on file uploads.
The response implements the Writable Stream interface. This is an EventEmitter with the following events:
Something like that:
// mockResponse.js
// The response implements the Writable Stream interface.
on: function(event, listener){
},
emit: function(event, args){
},
removeListener: function(event, listener){
},
Cheers
I believe we can improve our unit testing by implementing a more flexible framework, with more readable assertion library, better isolation of the unit of code being tested, and code coverage reporting. I propose that we:
I know this may be a matter of choice, but I believe mocha
to be a much better javascript unit testing framework than nodeunit
. These as just some of my reasons:
chai
)Again, this is probably just a matter of style choice, but I just like the readability of Chai's assertions.
Sinon is a great library for spying/mocking/stubbing. It is my go-to library for isolating my unit tests. I think it will be a great addition to our testing framework.
I like istanbul because it tracks statement, branch, and function coverage. It also includes both HTML and LCOV reporting out of the box.
I think we should implement these before our move to 2.0
. This will be the last minor release before starting work on 2.0
.
I am trying to use this library to make calls into my express app, but the data is returned with "res.send" and "res.end". So in my caller, I try to listen to those emitters, but they are all stubbed out! Why not use the real event module?
req = mocks.createRequest(..)
resp = mocks.createResponse(..)
resp.on('end', function() { check resp._getData });
app.handle(req,resp); // call into express
Hello, thanks for this, it is a time saver. I'm using createRequest currently. The reason I don't use createResponse is because it lacks a render method and some of my views do: return render(view, options);
Therefore in my tests suite I put something like this:
var mockResponse = function () {
return {
render: function (viewName, options, callback) {
this.viewName = viewName;
this.options = options;
this.callback = callback;
}
};
};
This allows me to test my view like this:
test("index route is defined", function () {
var req = httpMocks.createRequest({ method: 'GET', url: '/' }),
resp = mockResponse();
assert.isDefined(routes.index);
routes.index(req, resp);
assert.equal(resp.options.title, "Express");
assert.equal(resp.viewName, "pages/index");
});
I've played around with adding this to mockRequest.js. If you think it would be useful, let me know and I will try to submit a pull request.
The json object is wrong in the following code piece.
var res = httpMocks.createResponse({
EventEmitter: require('events').EventEmitter;
});
It should be:
var res = httpMocks.createResponse({
EventEmitter: require('events').EventEmitter
});
Node's API includes: https://nodejs.org/api/http.html#http_response_headerssent
This has two problems when mocking:
res.writeHead
after data is written to body, the mock just updates the header values so it appears to work OK (for some definition of OK - it's hard to tell from data output in all cases anyway).mockResponse.headersSent
is always undefined
so if your system under test relies on reading that value in order to prevent accidentally writing headers again, it will not behave correctly during testing.In real-life, if you call writeHead
after sending body bytes, node will not error but will write corrupt chunked stream with repeated header block.
I think it could be fixed by:
headersSent
param to response, defaulting to false
true
on first write of body data. (note node does not send headers when you call writeHead
, only on first byte of body.While this still wouldn't be 100% match for real node behaviour (you'd have to make writeHead
output raw headers directly into the body data stream for that), it's enough that code relying on that param being set will still work correctly and you can write a test to assert this unambiguously.
Will make a PR.
The version currently on npm didn't work for me, but master works fine. Please publish an update.
I think we should consider replacing JSHint with ESLint.
I wanted to introduce coding style checks to our coding standards, but given that JSHint has deprecated all coding style checks, we would need another tool for that task. I considered recommending JSCS, but that would mean we would have to run two linters.
With ESLint we get both, static code analysis and style checks, all in one tool.
I cannot find a way to test the statusMessage set on the response. I see a response._getStatusCode()
for the code, but nothing for the message. Am I missing something?
I have a patch for this in my project, and will probably look to submit it here if indeed there is no way to get it.
If a path but no url is supplied to createRequest, the path is ignored.
This should be an easy fix, I'll submit a pull request when I've fixed it.
The library works great, but since my controller uses express and has a few extra libraries injected in via app.use like express-validator, the request fails out because it doesn't have a few of the methods.
It looks like someone set it up for an express request, but there is no documentation on how to use it.
The Node ServerResponse class has a property for detecting if headers have been sent:
http://nodejs.org/api/http.html#http_response_headerssent
This would be great if it were supported by this module. Thanks!
The mockRequest.js
does not have a header, or get method, which Express does have.
Hello, im using multiparty extension for nodejs.
How can i test my app with node-mocks-http ?
I try
files {'file','data:image/png;base64,iVB....'}
files {'file',Payload data from curl'}
nothing(
can you show how to do that?
Thnks for the great testing tool!!!
Hi team,
I would like to use mock-express to test out some init files in my Express.js application. These init files, among other functions, send my express app through app.use (example.)
I don't see a way to access mock-express.js. I've tried things like node-mocks-http/lib/express/mock-express
, but then that fails with errors like:
Error: Cannot find module './node/http'
Could I create a PR to add mock-express into the exports
at the bottom of /lib/http-mock.js
?
var response = require('./mockResponse');
var express = require('./express/mock-express');
...
exports.createResponse = response.createResponse;
exports.createExpress = express;
exports.createMocks = createRequestResponse;
Have you tried this and would that simple change open up mock-express to be used, or would there be more changes that would be required to mock up my Express application?
thanks,
Scott
Caused by below piece of code (in mockResponse.js
). eventEmitter
passed in via options overrides included EventEmitter
module, then trying to create new instance triggers TypeError: object is not a function
var EventEmitter = require('./mockEventEmitter');
//...
if (options.eventEmitter) {
EventEmitter = options.eventEmitter;
}
var writableStream = new WritableStream();
var eventEmitter = new EventEmitter();
node.js:0.10.24
express:4.12.3
express-session:1.10.4
body-parser:1.12.1
cookie-parser:1.3.4
node-mocks-http:1.2.7
at Function.proto.process_params (/home/bae/app/node_modules/express/lib/router/index.js:321:12)
at /home/bae/app/node_modules/express/lib/router/index.js:270:7
at trim_prefix (/home/bae/app/node_modules/express/lib/router/index.js:300:13)
at Layer.handle_error (/home/bae/app/node_modules/express/lib/router/layer.js:54:12)
at next (/home/bae/app/node_modules/express/lib/router/index.js:246:14)
at /home/bae/app/node_modules/express/lib/router/index.js:603:15
at /home/bae/app/node_modules/express/node_modules/finalhandler/index.js:96:5
at send (/home/bae/app/node_modules/express/node_modules/finalhandler/index.js:135:3)
at unpipe (/home/bae/app/node_modules/express/node_modules/finalhandler/index.js:153:12)
at IncomingMessage.Readable.unpipe (_stream_readable.js:633:12)
TypeError: Cannot read property 'pipesCount' of undefined
Having an option for xhr that would be set to true would be really helpful
It should set req.xhr
to true
and req.headers["x-requested-with"]
to 'XMLHttpRequest'
and anything else that I needed to replicate the xhr request?
JSON method for response object in node-mocks-http accepts two arguments: status code and data object. The latest express implementation, only accepts one argument: data object. The problem with this discrepancy is that, if you call "status" and "json" method in a chain(while using node-mocks-http), the status code set through status method is overwritten in json method.
Your package is depending on: lodash.assign
which was recently deprecated.
The warning:
npm WARN deprecated [email protected]: This package is deprecated. Use Object.assign.
The tree:
├─┬ [email protected]
│ ├── [email protected]
Please refactor accordingly.
I need to mock doing req.on('end', onEnd);
and the mock request class does not have the event emitter methods.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.