Mocking using mocha in NodeJs - node.js

How can I mock a client and a server in Mocha using NodeJs.
Specifically, I have the following code:
app.post ('path name', function (req, res) {
// Some Action
res.send(response);
});
I want to mock the req, res parameters and test res (status, header, message).

Mocha itself doesn't provide mock/stub/spy type functionality. Sinon is a popular library that does. The home page includes examples of testing ajax as well as their Fake XMLHTTPRequest object.

I found Node-Fakeweb useful
var request = require('request');
// Mocking a client request
request.get({ uri: 'URI', body: 'body' }, function (err, resp, body) {
// Some Action
});
});

You can use mocha with supertest to mock a request. Here is a wonderful tutorial about how to do it:
http://thewayofcode.wordpress.com/2013/04/21/how-to-build-and-test-rest-api-with-nodejs-express-mocha/

Related

How can I use nock.js to mock node-webshot requests?

What is proper way to mock requests sent by node Webshot during a test using nock.js?
I tried following code to capture mocked response of http://example.com/foo.html as foo.png but the mock doesn't seem to work.
const nock = require("nock");
const webshot = require("webshot");
describe("mock webshot request", function(){
this.timeout(20000);
beforeEach(function(){
nock("http://example.com").persist().get("/foo.html").reply(200, "<h1>Foo</h1>");
});
afterEach(function () {
nock.cleanAll();
});
it("captures mocked response", function(done){
webshot("http://example.com/foo.html", "foo.png",function(err) {
nock.isDone();
if(!err) done();
});
});
});
Edit:
The solution was to pass mocked response body to Webshot rather than url:
webshot("<h1>Foo</h1>", ...
Nock expects the http request to happen in the same process.
Note: node-webshot is a wrapper for PhantonJS which run in another process.
In your case Nock is setup in one process, but the http request happens in another process. So you cannot mock http request done by node-webshot like the way your are currently doing.
What you need is support for mocking http request built into node-webshot i.e you will have to add this feature to node-webshot if it doesn't have it.

Making external get request with Express

so I have the following Scenario; I have a private API key that Angular will show in XHR request. To combat this, I decided to use Express as a proxy and make server side requests. However, I cannot seem to find documentation on how to make my own get requests.
Architecture:
Angular makes request to /api/external-api --> Express handles the route and makes request to externalURL with params in req.body.params and attaches API key from config.apiKey. The following is pseudocode to imitate what I'm trying to accomplish:
router.get('/external-api', (req, res) => {
externalRestGetRequest(externalURL, req.body.params, config.apiKey)
res.send({ /* get response here */})
}
You are half way there! You need something to make that request for you. Such as the npm library request.
In your route something like
var request = require('request');
router.get('/external-api', function(req, res){
request('http://www.google.com', function (error, response, body) {
console.log('error:', error); // Print the error if one occurred and handle it
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
res.send(body)
});
})
This allows you to make any type of request using whatever URL or API keys you need. However it's important to note you also need to handle any errors or bad response codes.
The accepted answer is good, but in case anyone comes across this question later, let's keep in mind that as of February, 2020, request is now deprecated.
So what can we do? We can use another library. I would suggest Axios.
Install it and do something like:
const axios = require('axios')
const url = "https://example.com"
const getData = async (url) => {
try {
const response = await axios.get(url)
const data = response.data
console.log(data)
} catch (error) {
console.log(error)
}
}
getData(url)

Chai/Moka -> TypeError: request.get(...).expect is not a function

First time with TDD. I'm using the duo Chai/Moka after reading some article online for my NodeJS API.
I already made few dumb test to learn how to use those. Now I want test my API so I created a route :
app.get('/hello', function(req, res) {
res.status(200).send('Hello World!')
})
I try a test like this :
var request = require('superagent')
var expect = require('Chai').expect
[...]
describe('When request baseURL/hello', function(){
it('should salute you !', function (done) {
request
.get(baseURL + '/hello')
.expect(200)
.end(function(err, res){
if(err) return done(err)
done()
})
})
})
I have the fail output :
TypeError: request.get(...).expect is not a function
If I comment the expect line everything is working. I try this route with Postman and I have a 200 status code like expected.
I think you're using the wrong test module: you need supertest, not superagent.
Just install the supertest module, change the require line, and try again.

How to mock request and response in nodejs to test middleware/controllers?

My application has several layers: middleware, controllers, managers. Controllers interface is identical to middlewares one: (req, res, next).
So my question is: how can I test my controllers without starting the server and sending 'real' requests to localhost. What I want to do is to create request, response instances as nodejs does and then just call controllers method.
Something like this:
var req = new Request()
var res = new Response()
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)
Any advice is highly appreciated. Thanks!
P.S. the reason why I want to do this is that at the end I would like to test whether the response object contains correct variables for the jade views.
There's a semi decent implementation at node-mocks-http
Require it:
var mocks = require('node-mocks-http');
you can then compose req and response objects:
req = mocks.createRequest();
res = mocks.createResponse();
You can then test your controller directly:
var demoController = require('demoController');
demoController.login(req, res);
assert.equal(res.json, {})
caveat
There is at time of writing an issue in this implementation to do with the event emitter not being fired.
Since JavaScript is a dynamically typed language you can create mock objects and passing them to your controllers as follow:
var req = {};
var res = {};
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)
If your controller needs a particular piece of data or functionality from your request or response object you'll need to provide such data or functionality in your mocks. For example,
var req = {};
req.url = "http://google.com"; // fake the Url
var res = {};
res.write = function(chunk, encoding) {
// fake the write method
};
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)
I would try using dupertest for this. It's a node module I created for the very purpose of easy controller testing without having to spin up a new server.
It keeps the familiar syntax of node modules like request or supertest, but again, without the need to spin up a server.
It runs a lot like Hector suggested above, but integrates with a test framework like Jasmine to feel a little more seamless.
An example relating to your question may look like:
request(controller.get_user)
.params({id: user_id})
.expect(user, done);
Or the more explicit longhand version:
request(controller.get_user)
.params({id: user_id})
.end(function(response) {
expect(response).toEqual(user);
done();
});
Note: the examples assume user_id and user are defined somewhere, and that the controller grabs and returns a user based on id.
Edit: reading your response to an answer above, I will admit the downside currently is that this module does not integrate a more robust mock request or response object by default. dupertest makes it super easy to extend and add properties to both req and res, but by default they are pretty bare.
If you want to use the real req and res objects, you have to send real requests to the server. However this is much easier than you might think. There are a lot of examples at the express github repo. The following shows the tests for req.route
var express = require('../')
, request = require('./support/http');
describe('req', function(){
describe('.route', function(){
it('should be the executed Route', function(done){
var app = express();
app.get('/user/:id/edit', function(req, res){
// test your controllers with req,res here (like below)
req.route.method.should.equal('get');
req.route.path.should.equal('/user/:id/edit');
res.end();
});
request(app)
.get('/user/12/edit')
.expect(200, done);
})
})
})
A bit old post, but I would like to give my 2 cents. The approach you want to take depends on whether you are doing unit testing or integration testing. If you are going down the route of using supertest, that means you are running the actual implementation code and that means you are doing integration testing. If that's what you want to do this approach is fine.
But if you are doing unit testing, you would mock req and res objects (and any other dependencies involved). In the below code (non-relevant code removed for brevity), I am mocking res and giving just a mock implementation of json method, as that's the only method I need for my tests.
// SUT
kids.index = function (req, res) {
if (!req.user || !req.user._id) {
res.json({
err: "Invalid request."
});
} else {
// non-relevent code
}
};
// Unit test
var req, res, err, sentData;
describe('index', function () {
beforeEach(function () {
res = {
json: function (resp) {
err = resp.err;
sentData = resp.kids;
}
};
});
it("should return error if no user passed in request", function () {
req = {};
kidsController.index(req, res);
expect(err).to.equal("Invalid request.");
});
/// More tests....
})
Take a look at node-tdd and the useNock flag. It builds on top of mocha and nock and automatically creates and uses a recording file for each test.
We love that it's so easy to use. Basically just "enable and forget" and focus on writing requests / test cases. If requests for a test change, one still needs to delete or adjust the recording file, but at least it's entirely separate from the code.

node.js: Mock http request and response

Is there convenient way to mock the HTTP Request and Response objects for unit testing middlewares?
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.
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"}
i'm using nodejutsu mock:
https://github.com/nodejitsu/mock-request
Maybe this is what you are looking for.
I wrote a library to mock out the responses of requests made via standard HTTP or via the request model:
https://github.com/ctide/fakeweb
Check out https://github.com/timsavery/node-hmock or npm install hmock...any feedback welcome! The solution has worked well for me thus far.
Mockery looks great for this.
Essentially it hijacks require calls, and returns a different object/function stub that you specify.
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()
})
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.
I encourage you to use motty. why do we need an another code?

Resources