【问题标题】:Mocking NodeJS request and response with Nock使用 Nock 模拟 NodeJS 请求和响应
【发布时间】:2017-04-15 02:51:56
【问题描述】:

我正在尝试掌握工具Nock,以便模拟来自我的代码执行调用的请求和响应。我使用 npm request 作为简单的 HTTP 客户端来请求后端 REST API,使用 Chai 请求期望库和 Mocha 来运行我的测试。这是我用于测试的代码:

 var nock = require('nock');
 var storyController = require('../modules/storyController');

 var getIssueResponse = {
   //JSON object that we expect from the API response.
 }

 it('It should get the issue JSON response', function(done) {
   nock('https://username.atlassian.net')
   .get('/rest/api/latest/issue/AL-6')
   .reply(200, getIssueResponse);

   storyController.getStoryStatus("AL-6", function(error, issueResponse) {
   var jsonResponse = JSON.parse(issueResponse);

   expect(jsonResponse).to.be.a('object');
   done();
 })
});

这是执行 GET 请求的代码:

 function getStoryStatus(storyTicketNumber, callback) {
   https.get('https://username.atlassian.net/rest/api/latest/issue/' + storyTicketNumber, function (res) {

   res.on('data', function(data) {
    callback(null, data.toString());
   });

   res.on('error', function(error) {
    callback(error);
   });
  })
 }

这个单一的测试通过了,我不明白为什么。看起来它实际上是在打一个真正的电话,而不是使用我的假诺克请求/响应。如果我评论 nock 部分或更改:

 .reply(200, getIssueResponse) to .reply(404)

它不会破坏测试并且没有任何变化,我没有对我的 nock 变量做任何事情。有人可以用一个清晰​​的例子来解释我如何使用 Nock 在我的 NodeJS http-client 中模拟请求和响应吗?

【问题讨论】:

  • 响应结束回调在哪里?
  • @Dhirendra 我认为在发布的代码中很清楚,回调是我传递的称为“回调”的函数,响应是 data.toString ()

标签: javascript node.js request mocking nock


【解决方案1】:

TLDR:我认为你的代码做的比它告诉你的要多。

重要提示:当在"stream mode" 中发送http 请求时,data 事件可能(并且可能确实)被触发多次,每次触发一个“块”数据,通过 Internet 块可以在 1400 到64000 字节,所以预计会有 多个 回调调用(这是一种非常特殊的坏事)

作为一个简单的建议,您可以尝试使用request 或只是连接接收到的数据,然后在end 事件上调用回调。

我已经使用后一种技术尝试了一个非常小的 sn-p

var assert = require('assert');
var https = require('https');
var nock = require('nock');

function externalService(callback) {
  // directly from node documentation:
  // https://nodejs.org/api/https.html#https_https_get_options_callback
  https.get('https://encrypted.google.com/', (res) => {

    var data = '';
    res.on('data', (d) => {
      data += d;
    });

    res.on('end', () => callback(null, JSON.parse(data), res));
  // on request departure error (network is down?)
  // just invoke callback with first argument the error
  }).on('error', callback);
}


describe('Learning nock', () => {
  it('should intercept an https call', (done) => {
    var bogusMessage = 'this is not google, RLY!';

    var intercept = nock('https://encrypted.google.com').get('/')
      .reply(200, { message: bogusMessage });

    externalService((err, googleMessage, entireRes) => {
      if (err) return done(err);

      assert.ok(intercept.isDone());
      assert.ok(googleMessage);
      assert.strictEqual(googleMessage.message, bogusMessage);
      assert.strictEqual(entireRes.statusCode, 200);

      done();
    });

  })
})

它工作得很好,即使使用on('data')

编辑:

Reference on how to handle correctly a stream

我已将示例扩展为成熟的 mocha 示例

【讨论】:

  • 感谢您的回答,但我看不到您在哪里使用“结束”事件以及您的测试期望在哪里?我不确定如何使用 Nock 模拟 HTTP 请求,您的代码与我已有的代码相比并没有多大作用。也许我错了,但你能解释一下吗?
  • 做 expect(res.statusCode).to.equal(404) 仍然会让测试通过
  • 我现在已经做了一个完整的测试,但是它当然通过了。我认为你应该开始隔离问题。尝试使用更简单的 request/request 接口而不是 vanilla node.js 调用,然后检查 mocha 是否正确运行,以及许多其他无法在此处列出的细节
  • 非常感谢,我现在了解更多了!我试图弄清楚的最后一件事:是否可以断言或期望从模拟响应中返回的 statusCode?​​span>
猜你喜欢
  • 1970-01-01
  • 2013-06-01
  • 2020-09-02
  • 2021-03-27
  • 2018-05-09
  • 2013-03-23
  • 1970-01-01
  • 2015-10-11
  • 1970-01-01
相关资源
最近更新 更多