Reputation: 3678
I've written a small node
module that makes a http
request and I am having trouble testing it.
The code in question looks like this:
module.exports = (function () {
var http = require("http"),
Promise = require("promise");
var send = function send(requestOptions, requestBody) {
return new Promise(function (resolve, reject) {
http.request(requestOptions, function (response) {
var responseChunks = [];
response.on('data', function (chunk) {
responseChunks.push(chunk);
});
response.on('end', function () {
resolve(Buffer.concat(responseChunks));
});
response.on('error', function (e) {
reject(e);
});
}).end(requestBody);
});
};
return {
send: send
}
and I am trying to test my send
method, in particular the callback function that is invoked by http.request
.
I think what I need to do is to mock or stub the response
object from http.request
so that I can then test the execution of the callback function. But I can't figure out how to do that.
If it's of any relevance I am using node
v4.1, jasmine
v2.3, and sinon
v1.17
Upvotes: 4
Views: 9832
Reputation: 5480
I know this was asked a long time back, but just in case anyone is looking for quick solution to this which doesn't involve setting up additional mock servers, here it goes.
You can use Jasmine's spyOn
and returnValue
to mock the response of Node's HTTP package. The Node.js doc here reads:
A spy can stub any function and tracks calls to it and all arguments.
And here it later reads:
By chaining the spy with
and.returnValue
, all calls to the function will return a specific value.
So all you have to do is this:
spyOn(http, "request").and.returnValue(
//Your mock response goes here.
);
I hope this helps others.
Upvotes: 0
Reputation: 111
Instead of stubbing, you can try creating a local or "mock" server that responds to your requests. This avoids having to stub out http.request. One of the benefits of a local server is this method should work whether you are using http.request, XMLHttpRequest, or a similar method to grab an online resource.
You can try mock server. With it, you can create a fake server to fulfill your requests.
npm install mockserver-grunt --save-dev
npm install mockserver-client --save-dev
In your Spec (or test), you can use the following (change to suit your needs):
var mockServer = require("mockserver-grunt");
var mockServerClient = require("mockserver-client").mockServerClient;
beforeAll(function(done) {
// start the server
mockServer.start_mockserver({
serverPort: 1080,
verbose: true
});
// setup how to respond
let response = {name:'value'};
let statusCode = 203;
mockServerClient("localhost", 1080).mockSimpleResponse('/samplePath', response, statusCode);
setTimeout(function() {
// give time for the mock server to setup
done();
}, 4000);
});
it("should be able to GET an online resource", function(done) {
// perform tests, send requests to http://localhost:1080/samplePath
}
This will start the server on port 1080. Any requests made to http://localhost:1080/samplePath will receive the provided response.
In a similar manner, the server can be shutdown at the end of your test:
afterAll(function() {
mockServer.stop_mockserver({
serverPort: 1080,
verbose: true
});
});
When the server is first started, it will attempt to download a jar file required for the server. This is a one time download (as far as I know). If it is not provided enough time, it will not fully download, and you will end up with an invalid or corrupt jar file. To correct this, you can download the jar file yourself. The link is provided in the run. For me, this was located at https://oss.sonatype.org/content/repositories/releases/org/mock-server/mockserver-netty/3.10.6/mockserver-netty-3.10.6-jar-with-dependencies.jar. Most likely, you will want to navigate to the latest version.
Since I originally posted, I found Express JS. Express starts a server instance much faster than Mock Server. You also do not have to worry about a jar file.
npm install express --save-dev
var express = require('express');
var app = express();
var port = 3000;
var server;
beforeAll(function() {
server = app.listen(port, function() {
console.log("Listening on port " + port);
});
app.get('/samplePath', function (req, res) {
res.send("my response");
});
});
afterAll(function() {
// shutdown
server.close();
});
it("should be able to GET an online resource", function(done) {
// perform tests, send requests to http://localhost:3000/samplePath
}
If you want to get fancy, you can return the path that you use. For example, if you go to http://localhost:3000/helloworld, the return value will be helloworld. You can adapt this to suit your needs.
app.get('/*', function (req, res) {
res.send(req.params[0]);
});
If you need to force the code down an error path, you can use
res.status(404) // HTTP status 404: NotFound
.send('Not found');
Source: How to programmatically send a 404 response with Express/Node?
Express JS can be configured to use HTTPS. With openssl, a self-signed certificate can be created using:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
Source: How to create a self-signed certificate with openssl?
Update the express js code with the following to use HTTPS.
const secureOptions = {
key: fs.readFileSync("./spec/ExpressServer/key.pem"),
cert: fs.readFileSync("./spec/ExpressServer/cert.pem")
};
var secureServer = https.createServer(secureOptions, app);
Note: You may have to configure the security of your applications to allow a self-signed certificate for HTTPS.
Upvotes: 3
Reputation: 747
The mocha testing frame work and Should.JS (assertion lib) is pretty nice.
See the getting started section: https://mochajs.org/
Essentially, you use the mocha
framework to create test cases. Then you use the should.js
node module to make assertions (facts about what should happen).
You can install it via npm install mocha
& npm install should
module.exports.run = function() {
var chalk = require('chalk');
var should = require('should');
var http = require("http");
describe('test lib description', function(done){
it('Individual Test Case description', function(done) {
function send(requestOptions, requestBody) {
return new Promise(function (resolve, reject) {
http.request(requestOptions, function (response) {
var responseChunks = [];
// Assertions using Should.JS
// Example: The http status code from the server should be 200
should.equal(response.statusCode , 200);
response.should.have.property('someProperty');
response.should.have.property('someProperty','someVal');
response.on('data', function (chunk) {
responseChunks.push(chunk);
done(); // Needed To tell mocha we are ready to move on to next test
});
response.on('end', function () {
resolve(Buffer.concat(responseChunks));
done();
});
response.on('error', function (e) {
reject(e);
done();
});
}).end(requestBody);
});
};
});
});
}
node ./node_modules/mocha/bin/mocha
testFile
Upvotes: 0