测试节点中的失败请求

时间:2017-06-13 19:32:12

标签: javascript node.js promise sinon

我有一些代码如下:

var request = require('request');

function Service(){
 this._config = require('../path/to/config.json');
}

Service.prototype.doThing = function(){
  return new Promise(function(resolve, reject){
    request.post(url, {payload}, function(error, response, body){
      //handle response
      resolve(true);
    }).on('error', function(err){
      //handle errors
      resolve(false);
    });
  });
}

我正在尝试测试运行错误的块,但由于承诺而遇到困难。我正在使用mocha进行测试运行,使用sinon进行存根。我能够存根请求,以便我可以计算on方法被调用的次数,但是包含的Promise永远不会解析。

有一些软件包可以与sinon一起处理promises(我已经尝试过sinon-as-promise和sinon-stub-promise),但我必须存根整个doThing方法才能正确解析。我将非常感谢有关测试此代码的替代方法的任何输入或可能更容易测试的替代代码结构。

有问题的测试(挂起等待doThing承诺返回)如下:

context('when the server is unavailable', function(){
  beforeEach(function() {
    var onStub = sinon.stub();
    requestStub = {post: function(){ return {on: onStub}}};
    Service = proxyquire('path/to/service', {request: requestStub});
    service = new Service();
  });

  it('should not set the auth key', function(){
    return service.doThing().then(function(x){
      return assert(onStub.calledOnce);
    });
  });
});

谢谢!

1 个答案:

答案 0 :(得分:1)

总结显而易见的,您的问题是您不能控制request对象,或者更确切地说是来自post方法的响应。如果您可以控制,则可以使用doThing方法测试所有不同的代码路径。

您有三种可能性来控制来自request的响应:

  1. 存档网络层(使用Nock之类的内容),以便您可以控制HTTP层移交给request库的内容。
  2. 使用依赖注入来注入可用于代替request.post的存根(需要修改代码)
  3. 使用链接接缝,将require()调用返回的对象替换为您控制的存根对象。这当然是你所做的。
  4. 就个人而言,我会选择2,因为它不需要额外的框架,易于推理且易于实现。您可以参考this quite elaborate example,但您的案例中所需的代码很少。

    无论如何,既然你已经选择了选项3,我可能会沿着那条路走下去:-)问题是你如何删除post方法。有没有会打电话回电话?

    我会将post存根改为:

    post: (url, options, cb) => { 
      cb(null, null, null); // will resolve your promise in the module
      return { on: onStub }; 
    }
    

    当然,如果您稍后需要对值进行操作,那么传入回调的null可能是其他内容。