I want to test the error in a request return. I'm using nock in my tests, how can I force Nock to provoke an error? I want to achieve 100% test coverage and need to test err branch for that
request('/foo', function(err, res) { if(err) console.log('boom!'); });
Never enter in the if err branch. Even if hit err is a valid response, my Nock line in test looks like this
nock('http://localhost:3000').get('/foo').reply(400);
edit: thanks to some comments:
Nock is an HTTP server mocking and expectations library. You can use this library to test frontend modules that are performing HTTP requests. You can test in isolation because Nock lets you dictate what our API responses will be.
Nock is an HTTP server mocking and expectations library. Nock works by overriding Node's http. request function. It helps us mock calls to API and specifies what URLs we want to listen for, and responds with predefined responses, just like real APIs would.
Nock is an HTTP server mocking and expectations library for Node. js. Nock works by overriding the http. request and http. ClientRequest functions, intercepting all requests made to a specified URL and returning specified responses that mimic the data that the real URL would return.
Use replyWithError. From the docs:
nock('http://www.google.com') .get('/cat-poems') .replyWithError('something awful happened');
When you initialise a http(s) request with request(url, callback)
, it returns an event emitter instance (along with some custom properties/methods).
As long as you can get your hands on this object (this might require some refactoring or perhaps it might not even be suitable for you) you can make this emitter to emit an error
event, thus firing your callback with err
being the error you emitted.
The following code snippet demonstrates this.
'use strict'; // Just importing the module var request = require('request') // google is now an event emitter that we can emit from! , google = request('http://google.com', function (err, res) { console.log(err) // Guess what this will be...? }) // In the next tick, make the emitter emit an error event // which will trigger the above callback with err being // our Error object. process.nextTick(function () { google.emit('error', new Error('test')) })
EDIT
The problem with this approach is that it, in most situations, requires a bit of refactoring. An alternative approach exploits the fact that Node's native modules are cached and reused across the whole application, thus we can modify the http
module and Request will see our modifications. The trick is in monkey-patching the http.request()
method and injecting our own bit of logic into it.
The following code snippet demonstrates this.
'use strict'; // Just importing the module var request = require('request') , http = require('http') , httpRequest = http.request // Monkey-patch the http.request method with // our implementation http.request = function (opts, cb) { console.log('ping'); // Call the original implementation of http.request() var req = httpRequest(opts, cb) // In next tick, simulate an error in the http module process.nextTick(function () { req.emit('error', new Error('you shall not pass!')) // Prevent Request from waiting for // this request to finish req.removeAllListeners('response') // Properly close the current request req.end() }) // We must return this value to keep it // consistent with original implementation return req } request('http://google.com', function (err) { console.log(err) // Guess what this will be...? })
I suspect that Nock does something similar (replacing methods on the http module) so I recommend that you apply this monkey-patch after you have required (and perhaps also configured?) Nock.
Note that it will be your task to make sure you emit the error only when the correct URL is requested (inspecting the opts
object) and to restore the original http.request()
implementation so that future tests are not affected by your changes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With