Nock is an HTTP mocking and expectations library for Node.js
Nock can be used to test modules that perform HTTP requests in isolation.
For instance, if a module performs HTTP requests to a CouchDB server or makes HTTP requests to the Amazon API, you can test that module in isolation.
$ npm install nock
On your test, you can setup your mocking object like this:
var nock = require('nock');
var couchdb = nock('http://myapp.iriscouch.com')
.get('/users/1')
.reply(200, {_id: "123ABC", _rev: "946B7D1C", username: 'pgte', email: 'pedro.teixeira@gmail.com'});
This setup says that we will intercept every HTTP call to http://myapp.iriscouch.com
.
It will intercept an HTTP GET request to '/users/1' and reply with a status 200, and the body will contain a user representation in JSON.
Then the test can call the module, and the module will do the HTTP requests.
When you setup an interceptor for an URL and that interceptor is used, it is removed from the interceptor list. This means that if you can intercept 2 or more calls to the same URL and return different things on each of them. It also means that you must setup one interceptor for each request you are going to have, otherwise nock will throw an error because that URL was not present in the interceptor list.
You can specify the request body to be matched as the second argument to the get
, post
, put
or delete
specifications like this:
var scope = nock('http://myapp.iriscouch.com')
.post('/users', {username: 'pgte', email: 'pedro.teixeira@gmail.com'})
.reply(201, {ok: true, id: "123ABC", rev: "946B7D1C"});
The request body can be a string or a JSON object.
You can specify the return status code for a path on the first argument of reply like this:
var scope = nock('http://myapp.iriscouch.com')
.get('/users/1')
.reply(404);
You can also specify the reply body as a string:
var scope = nock('http://www.google.com')
.get('/')
.reply(200, "Hello from Google!");
or as a JSON-encoded object:
var scope = nock('http://myapp.iriscouch.com')
.get('/')
.reply(200, {username: 'pgte', email: 'pedro.teixeira@gmail.com', _id: "4324243fsd"});
or even as a file:
var scope = nock('http://myapp.iriscouch.com')
.get('/')
.replyWithFile(200, __dirname + '/replies/user.json');
Instead of an object or a buffer you can also pass in a callback to be evaluated for the value of the response body:
var scope = nock('http://www.google.com')
.filteringRequestBody(/.*/, '*')
.post('/echo', '*')
.reply(201, function(uri, requestBody) {
return requestBody;
});
You can specify the reply headers like this:
var scope = nock('http://www.headdy.com')
.get('/')
.reply(200, "Hello World!", {'X-My-Headers': 'My Header value'});
You can also specify default reply headers for all responses like this:
var scope = nock('http://www.headdy.com')
.defaultReplyHeaders({'X-Powered-By': 'Rails', 'Content-Type': 'application/json'})
.get('/')
.reply(200, 'The default headers should come too');
Nock supports any HTTP verb, and it has convenience methods for the GET, POST, PUT, HEAD and DELETE HTTP verbs.
You can intercept any HTTP verb using .intercept(path, verb [, requestBody [, options]])
:
scope('http://my.domain.com')
.intercept('/path', 'PATCH')
.reply(304);
By default nock assumes HTTP. If you need to use HTTPS you can specify the https://
prefix like this:
var scope = nock('https://secure.my.server.com')
// ...
You are able to specify a non-standard port like this:
var scope = nock('http://my.server.com:8081')
...
You can chain behaviour like this:
var scope = nock('http://myapp.iriscouch.com')
.get('/users/1')
.reply(404)
.post('/users', {username: 'pgte', email: 'pedro.teixeira@gmail.com'})
.reply(201, {ok: true, id: "123ABC", rev: "946B7D1C"})
.get('/users/123ABC')
.reply(200, {_id: "123ABC", _rev: "946B7D1C", username: 'pgte', email: 'pedro.teixeira@gmail.com'});
You can also filter the URLs based on a function.
This can be useful, for instance, if you have random or time-dependent data in your URL.
You can use a regexp for replacement, just like String.prototype.replace:
var scope = nock('http://api.myservice.com')
.filteringPath(/password=[^&]*/g, 'password=XXX')
.get('/users/1?password=XXX')
.reply(200, 'user');
Or you can use a function:
var scope = nock('http://api.myservice.com')
.filteringPath(function(path) {
return '/ABC';
})
.get('/ABC')
.reply(200, 'user');
You can also filter the request body based on a function.
This can be useful, for instance, if you have random or time-dependent data in your URL.
You can use a regexp for replacement, just like String.prototype.replace:
< 9220 div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="var scope = nock('http://api.myservice.com') .filteringRequestBody(/password=[^&]*/g, 'password=XXX') .post('/users/1', 'data=ABC&password=XXX') .reply(201, 'OK');">var scope = nock('http://api.myservice.com')
.filteringRequestBody(/password=[^&]*/g, 'password=XXX')
.post('/users/1', 'data=ABC&password=XXX')
.reply(201, 'OK');