在节点中testing失败的请求

我有一些如下所示的代码:

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

我试图testing运行错误的块,但由于承诺而有困难。 我正在使用摩卡进行testing运行,并使用了sinon进行testing。 我能够存根请求,以便我可以计算on方法被调用的次数,但是包含的Promise永远不会parsing。

有一些软件包可以和sinon一起处理promise(我已经尝试过sinon-promise和sinon-stub-promise),但是我必须存储整个doThing方法才能正确parsing。 我将不胜感激在任何方式来testing这个代码或替代的代码结构,可能更容易testing的input。

有问题的testing(等待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); }); }); }); 

谢谢!

总而言之,你的问题在于你不控制request对象,或者说是对它的post方法的响应。 如果你可以控制,你将能够在你的doThing方法中testing所有不同的代码path。

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

  1. 将networking层(使用像Nock这样的东西)留在networking层,这样就可以控制HTTP层传递给request库的内容。
  2. 使用dependency injection来注入一个可以代替request.post使用的存根(需要修改代码)
  3. 使用一个链接接缝来代替从你要控制的存根require() stub)对象中调用require()调用返回的对象。 这当然是你所做的。

就我个人而言,我会select2,因为这不需要额外的框架,很容易推理和易于实现。 你可以参考这个相当复杂的例子 ,但在你的情况下所需的代码是最小的。

无论如何,既然你已经select了选项3,我不妨去那条路:-)问题是你如何取消post方法。 有永远打电话给你的callback?

我会改变post存根这样的事情:

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

当然,传递给你的callback函数的null可能是其他值,你需要在后面的值上做些什么。