https://www.npmjs.com/package/nock#socket-timeout
What is nock?
nock is a HTTP mocking and expectations library for Node.
How can we install nock?
npm install nock
How can we setup nock?
Just add to our Node test cases:
var nock = require('nock');
How can we use nock to mock an HTTP call?
nock('https://davidwalsh.name')
.get('/users/22').reply(200, {
username: 'davidwalshblog',
firstname: 'David'
});
nock('https://davidwalsh.name')
.get('/content/homepage')
.reply(200, 'This is the HTML for the homepage');
nock('https://davidwalsh.name')
.get('/content/page-no-exist')
.reply(404, 'This page could not be found');
nock('https://davidwalsh.name')
.post('/users/detail')
.reply(200, {
firstname: 'David'
});
How can we narrow down GET and POST matches by setting the data or query strings?
nock('https://davidwalsh.name')
.post('/users/detail', { username: 'davidwalshblog' })
.reply(200, {
firstname: 'David'
});
How can we mock custom response header?
var scope = nock('https://davidwalsh.name')
.get('/')
.reply(200, 'Hello World!', {
'X-My-Headers': 'My Header value'
});
How can we do some advanced processing logic before responding to the request?
If you want to do some advanced processing logic before responding to the request, you can reply with a function instead:
nock('https://davidwalsh.name')
.post('/users/detail', { username: 'davidwalshblog' })
.reply(function() {
// Some logic
return [200, resultingContent];
});
In the above code, the parameter that we pass to the reply method is a function, and it returns an array. The first element of this array is the HTTP status code. The second element of this array is the response body. If we need to response with some response header, I guess we can put those response headers into the third element.
var scope = nock('http://www.google.com')
.filteringRequestBody(/.*/, '*')
.post('/echo', '*')
.reply(function(uri, requestBody) {
return [
201,
'THIS IS THE REPLY BODY',
{'header': 'value'} // optional headers
];
});
How does Nock work?
Nock works by overriding Node's http.request function. Also, it overrides http.ClientRequest too to cover for modules that use it directly.
Can we specify a regular expression for the hostname?
Yes. The request hostname can be a string or a RegExp:
var scope = nock('http://www.example.com')
.get('/resource')
.reply(200, 'domain matched');
var scope = nock(/example\.com/)
.get('/resource')
.reply(200, 'domain regex matched');
Can we specify a regular expression for a path?
Yes. The request path can be a string, a RegExp or a filter function and you can use any HTTP verb:
var scope = nock('http://www.example.com')
.get('/resource')
.reply(200, 'path matched');
var scope = nock('http://www.example.com')
.get(/source$/)
.reply(200, 'path using regex matched');
var scope = nock('http://www.example.com')
.get(function(uri) {
return uri.indexOf('cats') >= 0;
})
.reply(200, 'path using function matched');
What can the request body be?
The request body can be a string, a RegExp, a JSON object or a function.
var scope = nock('http://myapp.iriscouch.com')
.post('/users', {
username: 'pgte',
email: 'pedro.teixeira@gmail.com'
})
.reply(201, {
ok: true,
id: '123ABC',
rev: '946B7D1C'
});
var scope = nock('http://myapp.iriscouch.com')
.post('/users', /email=.?@gmail.com/gi)
.reply(201, {
ok: true,
id: '123ABC',
rev: '946B7D1C'
});
If the request body is a JSON object, a RegExp can be used to match an attribute value:
var scope = nock('http://myapp.iriscouch.com')
.post('/users', {
username: 'pgte',
password: /a.+/,
email: 'pedro.teixeira@gmail.com'
})
.reply(201, {
ok: true,
id: '123ABC',
rev: '946B7D1C'
});
If the request body is a function, return true if it should be considered a match:
var scope = nock('http://myapp.iriscouch.com')
.post('/users', function(body) {
return body.id === '123ABC';
})
.reply(201, {
ok: true,
id: '123ABC',
rev: '946B7D1C'
});
How can we specify the query string?
Nock understands query strings. Instead of placing the entire URL, you can specify the query part as an object:
nock('http://example.com')
.get('/users')
.query({name: 'pedro', surname: 'teixeira'})
.reply(200, {results: [{id: 'pgte'}]});
Does Nock support array-style/object-style query parameters?
Nock supports array-style/object-style query parameters. The encoding format matches with request module.
nock('http://example.com')
.get('/users')
.query({
names: ['alice', 'bob'],
tags: {
alice: ['admin', 'tester'],
bob: ['tester']
}
})
.reply(200, {results: [{id: 'pgte'}]});
Does Nock support passing a function to query?
Nock supports passing a function to query. The function determines if the actual query matches or not.
nock('http://example.com')
.get('/users')
.query(function(actualQueryObject){
// do some compare with the actual Query Object
// return true for matched
// return false for not matched
return true;
})
.reply(200, {results: [{id: 'pgte'}]});
How can we mock the entire url regardless of the passed query string?
nock('http://example.com')
.get('/users')
.query(true)
.reply(200, {results: [{id: 'pgte'}]});
How can we specify the response?
Use the reply method:
var scope = nock('http://myapp.iriscouch.com')
.get('/users/1')
.reply(404);
// response as string
var scope = nock('http://www.google.com')
.get('/')
.reply(200, 'Hello from Google!');
// response as JSON:
var scope = nock('http://myapp.iriscouch.com')
.get('/')
.reply(200, {
username: 'pgte',
email: 'pedro.teixeira@gmail.com',
_id: '4324243fsd'
});
// response with file:var scope = nock('http://myapp.iriscouch.com')
.get('/')
.replyWithFile(200, __dirname + '/replies/user.json');
Can we specify a response using data coming from a file?
Yes.
var scope = nock('http://myapp.iriscouch.com')
.get('/')
.replyWithFile(200, __dirname + '/replies/user.json');
Can we specify a response using a function?
Yes. 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;
});
An asynchronous function that gets an error-first callback as last argument also works:
var scope = nock('http://www.google.com')
.filteringRequestBody(/.*/, '*')
.post('/echo', '*')
.reply(201, function(uri, requestBody, cb) {
fs.readFile('cat-poems.txt' , cb); // Error-first callback
});
Note: When using a callback, if you call back with an error as first argument, that error will be sent in the response body, with a 500 HTTP response status code.
or, use an error-first callback that also gets the status code:
var scope = nock('http://www.google.com')
.filteringRequestBody(/.*/, '*')
.post('/echo', '*')
.reply(function(uri, requestBody, cb) {
setTimeout(function() {
cb(null, [201, 'THIS IS THE REPLY BODY'])
}, 1e3);
});
A Stream works too:
var scope = nock('http://www.google.com')
.get('/cat-poems')
.reply(200, function(uri, requestBody) {
return fs.createReadStream('cat-poems.txt');
});
How can we access original request and headers?
If you're using the reply callback style, you can access the original client request using this.req like this:
var scope = nock('http://www.google.com')
.get('/cat-poems')
.reply(function(uri, requestBody) {
console.log('path:', this.req.path);
console.log('headers:', this.req.headers);
// ...
});
How can we reply with string error?
nock('http://www.google.com')
.get('/cat-poems')
.replyWithError('something awful happened');
NOTE: This will emit an error event on the request object, not the reply.
How can we reply with a JSON error?
nock('http://www.google.com')
.get('/cat-poems')
.replyWithError({'message': 'something awful happened', 'code': 'AWFUL_ERROR'});
NOTE: This will emit an error event on the request object, not the reply.
How can we specify a request header?
var scope = nock('http://www.example.com', {
reqheaders: {
'authorization': 'Basic Auth'
}
})
.get('/')
.reply(200);
Can we use a function to specify a request header value?
Yes.
var scope = nock('http://www.example.com', {
reqheaders: {
'X-My-Headers': function (headerValue) {
if (headerValue) {
return true;
}
return false;
},
'X-My-Awesome-Header': /Awesome/i
}
})
.get('/')
.reply(200);
What happens if reqheaders is not specified or if host is not part of it?
If reqheaders is not specified or if host is not part of it, Nock will automatically add host value to request header.
What happens if no request headers are specified?
If no request headers are specified for mocking then Nock will automatically skip matching of request headers. Since host header is a special case which may get automatically inserted by Nock, its matching is skipped unless it was also specified in the request being mocked.
How does Nock handle the host request header?
Since host header is a special case which may get automatically inserted by Nock, its matching is skipped unless it was also specified in the request being mocked.
How can we have Nock fail the request if certain headers are present?
We can also have Nock fail the request if certain headers are present:
var scope = nock('http://www.example.com', {
badheaders: ['cookie', 'x-forwarded-for']
})
.get('/')
.reply(200);
When invoked with this option, Nock will not match the request if any of the badheaders are present.
How can we do basic authentication with Nock?
var scope = nock('http://www.example.com')
.get('/')
.basicAuth({
user: 'john',
pass: 'doe'
})
.reply(200);
How can we specify default reply headers for all responses?
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');
Or you can use a function to generate the default headers values:
var scope = nock('http://www.headdy.com')
.defaultReplyHeaders({
'Content-Length': function (req, res, body) {
return body.length;
}
})
.get('/')
.reply(200, 'The default headers should come too');
How can we include the Content-Length response header automatically?*
When using scope.reply() to set a response body manually, you can have the Content-Length header calculated automatically:
var scope = nock('http://www.headdy.com')
.replyContentLength()
.get('/')
.reply(200, { hello: 'world' });
This does not work with streams or other advanced means of specifying the reply body.
How can we automatically include the Date response header?
You can automatically append a Date header to your mock reply:
var scope = nock('http://www.headdy.com')
.replyDate(new Date(2015, 0, 1)) // defaults to now, must use a Date object
.get('/')
.reply(200, { hello: 'world' });
What are the HTTP verbs that Nock support?
Nock supports any HTTP verb, and it has convenience methods for the GET, POST, PUT, HEAD, DELETE, PATCH and MERGE HTTP verbs.
How can we use .intercept ?
You can intercept any HTTP verb using .intercept(path, verb [, requestBody [, options]]):
scope('http://my.domain.com')
.intercept('/path', 'PATCH')
.reply(304);
How can we specify the number of times to repeat the same response?
You are able to specify the number of times to repeat the same response:
nock('http://zombo.com').get('/').times(4).reply(200, 'Ok');
http.get('http://zombo.com/'); // respond body "Ok"
http.get('http://zombo.com/'); // respond body "Ok"
http.get('http://zombo.com/'); // respond body "Ok"
http.get('http://zombo.com/'); // respond body "Ok"
http.get('http://zombo.com/'); // respond with zombo.com result
nock('http://zombo.com').get('/').once().reply(200, 'Ok');
nock('http://zombo.com').get('/').twice().reply(200, 'Ok');
nock('http://zombo.com').get('/').thrice().reply(200, 'Ok');
How can we specify a delay response time?
You are able to specify the number of milliseconds that the response body should be delayed. Response header will be replied immediately. delayBody(1000) is equivalent to delay({body: 1000}).
nock('http://my.server.com')
.get('/')
.delayBody(2000) // 2 seconds
.reply(200, '<html></html>')
The 'response' event will occur immediately, but the IncomingMessage not emit it's 'end' event until after the delay.
You are able to specify the number of milliseconds that your reply should be delayed:
nock('http://my.server.com')
.get('/')
.delay(2000) // 2 seconds delay will be applied to the response header.
.reply(200, '<html></html>')
delay() could also be used as:
delay({
head: headDelayInMs,
body: bodyDelayInMs
}
nock('http://my.server.com')
.get('/')
.delay({
head: 2000, // header will be delayed for 2 seconds, i.e. the whole response will be delayed for 2 seconds.
body: 3000 // body will be delayed for another 3 seconds after header is sent out.
})
.reply(200, '<html></html>')
What is delayConnection?
delayConnection(1000) is equivalent to delay({head: 1000}).