如何用Nock测试请求中的错误?

时间:2014-12-30 16:27:12

标签: node.js nock

我想在请求返回中测试错误。我在测试中使用nock,如何强迫Nock引发错误?我希望实现100%的测试覆盖率,并且需要测试错误的分支

request('/foo', function(err, res) {
  if(err) console.log('boom!');
});

永远不要进入if err分支。即使hit err是一个有效的响应,我的测试中的Nock行看起来像这样

nock('http://localhost:3000').get('/foo').reply(400);

修改 感谢您的一些评论:

  • 我试图模拟请求中的错误。从节点手册: https://nodejs.org/api/http.html#http_http_request_options_callback 如果在请求期间遇到任何错误(使用DNS解析,TCP级别错误或实际的HTTP解析错误),则会出现错误'事件在返回的请求对象上发出
  • 错误代码(例如4xx)没有定义错误变量。我试图完全嘲笑,无论定义错误变量并评估为真的错误

4 个答案:

答案 0 :(得分:26)

使用replyWithError。 来自文档:

    nock('http://www.google.com')
   .get('/cat-poems')
   .replyWithError('something awful happened');

答案 1 :(得分:5)

当您使用request(url, callback)初始化http(s)请求时,它会返回一个事件发射器实例(以及一些自定义属性/方法)。

只要您可以抓住这个对象(这可能需要一些重构或者甚至可能不适合您),您可以使此发射器发出error事件,从而触发您的回调err是您发出的错误。

以下代码段演示了这一点。

'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'))
})

修改

这种方法的问题在于,在大多数情况下,它需要一些重构。另一种方法利用了Node的本机模块在整个应用程序中进行缓存和重用的事实,因此我们可以修改http模块, Request 将看到我们的修改。诀窍在于修补http.request()方法,并将自己的逻辑注入其中。

以下代码段演示了这一点。

'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...?
})

我怀疑 Nock 做了类似的事情(替换 http 模块上的方法)所以我建议您在之后应用这个猴子补丁你需要(也许还配置了?) Nock

请注意,确保仅在请求正确的URL时检查错误(检查opts对象)并恢复原始http.request()实现,以便将来的测试是不受您的更改影响。

答案 2 :(得分:0)

看起来你正在寻找一个关于nock请求的例外,这可能对你有帮助:

var nock = require('nock');
var google = nock('http://google.com')
               .get('/')
               .reply(200, 'Hello from Google!');

try{
  google.done();
}
catch (e) {
  console.log('boom! -> ' + e); // pass exception object to error handler
}

答案 3 :(得分:0)

发布将nockrequest-promise结合使用的最新答案。

让我们假设您的代码这样调用request-promise

require('request-promise')
  .get({
    url: 'https://google.com/'
  })
  .catch(res => {
    console.error(res);
  });

您可以像这样设置nock来模拟500错误:

nock('https://google.com')
  .get('/')
  .reply(500, 'FAILED!');

您的catch块将记录一个StatusCodeError对象:

{
  name: 'StatusCodeError',
  statusCode: 500,
  message: '500 - "FAILED!"',
  error: 'FAILED!',
  options: {...},
  response: {
    body: 'FAILED!',
    ...
  }
}

您的测试然后可以验证该错误对象。