2017-06-13 79 views
2

我有一些代码,如下所示:测试失败的请求在节点

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

我试图测试上的错误运行块,但由于其承诺的难度。我正在使用摩卡进行测试运行,并用sinon进行测试。我可以存根请求,以便可以统计on方法的调用次数,但包含的Promise永远不会解析。

有一些软件包可以和sinon一起处理promise(我试过sinon-as-promised和sinon-stub-promise),但是我必须存根整个doThing方法才能正确解析。我会感激任何输入的propper方式来测试这个代码或可能更容易测试的替代代码结构。

测试中的问题(即挂起等待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

只是对模块代码的评论。不要将状态值传递回你的'resolve'函数,而是在出现错误时执行'reject'方法。在大多数情况下更有意义:-) – oligofren

+0

我的回答对你有帮助吗?没有回复,upvote或指定的答案... – oligofren

+1

它帮助我扩大了我的整体知识,但它确实是一位同事,解决了我遇到的问题。在我自己写答案之前,我给了他一个回应的机会。 – biagidp

回答

1

总结很明显,你的问题在于你不控制request对象,或者更确切地说是来自其post方法的响应。如果你可以控制,你将能够在你的方法中测试所有不同的代码路径。

您有控制从request响应三种可能性:

  1. 存根网络层(使用类似Nock),这样你可以控制的HTTP层被移交给request库。
  2. 使用依赖注入注入可以代替的request.post使用(将需要修改代码)
  3. 使用环缝到将替代对象从require()调用返回与存根对象你控制存根。这当然是你所做的。

就我个人而言,我会选择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秒后进入回调可能是别的东西,你应该稍后需要做一些事情的价值。