174

以下测试表现异常:

it('应返回btc_ltc的汇率',函数(done){var对='btc_ltc';shapeshift.getRate(对).then(函数(数据){expect(data.pair).to.equal(pair);expect(data.rate).to.have.length(400);done();}).catch(函数(err){//对于失败的请求,这实际上应该是“.catch”,但//相反,当一次测试失败时,蔡似乎正在接受这一点完成(错误);})});

我应该如何正确处理被拒绝的承诺(并对其进行测试)?

我应该如何正确处理失败的测试(即:expect(data.rate).to.have.length(400);?

下面是我正在测试的实现:

var requestp=需要(“请求-请求”);var shapeshift=模块导出={};var url='http://shapeshift.io';shapeshift.getRate=函数(对){返回请求({url:url+'/rate/'+对,json:真的});};

4个答案4

重置为默认值
257

最简单的方法是使用Mocha在最新版本中的内置承诺支持:

it('应返回btc_ltc的汇率',function(){//未完成var对='btc_ltc';//注意回报return shapeshift.getRate(pair).then(function(data)){expect(data.pair).to.equal(pair);expect(data.rate).to.have.length(400);});// 没问题,因为承诺被拒绝了,它会解决的});

或者使用现代节点和异步/等待:

it('应返回btc_ltc的汇率',async()=>{//未完成常量对=“btc_ltc”;const data=等待shapeshift.getRate(pair);expect(data.pair).to.equal(pair);expect(data.rate).to.have.length(400);});

由于这种方法是端到端的承诺,所以测试更容易,而且您不必像考虑奇怪的情况那样思考奇怪的情况完成()到处都有电话。

这是Mocha目前相对于Jasmine等其他图书馆的优势。您可能还需要检查Chai如约而行这样会更容易(不.然后)但我个人更喜欢当前版本的清晰和简单

13
  • 4
    这是从什么版本的摩卡开始的?我得到一个确保在此测试中调用done()回调尝试使用摩卡2.2.5进行此操作时出错。
    – 斯科特
    评论 2015年6月19日19:16
  • 15
    @Scott不接受完成中的参数那会选择退出。 评论 2015年6月19日19:16
  • 2
    这对我很有帮助。删除完成在我的回调,并显式调用返回回调中的(承诺)就是我让它工作的方式,就像代码片段中的一样。 评论 2015年12月8日15:40
  • 5
    答案棒极了,效果很好。回头看那些文件,它就在那里——我想很容易错过。或者,不使用done()回调,您可以返回Promise。如果您正在测试的API承诺返回而不是进行回调,这将非常有用: 评论 2016年1月10日20:10
  • 4
    和斯科特有同样的问题。我没有通过完成参数到打电话,但这仍在发生。。。
    – 用户458541
    评论 2016年7月9日16:56
52

正如已经指出的那样在这里,摩卡的新版本已经实现了Promise-aware。但是,由于OP特别询问了Chai的情况,所以只有指出chai-as-promised公司为测试承诺提供干净语法的包:

使用chai-as-promised

以下是如何使用chai-as-promised来测试这两者决定拒绝承诺案例:

var chai=要求('chai');var期望=chai.expect;var chaiAsPromised=要求(“承诺的chai”);chai.use(chaiAsPromised);...它('按承诺解决',function(){return expect(Promise.resolve('woof')).to.finally.equal('wooff');});it('按承诺弹出',function(){return expect(Promise.reject('caw')).to.be.rejectedWith('cau');});

没有chai-as-promised

为了真正清楚测试的内容,下面是没有chai-as-promised的相同示例:

它('按承诺解决',function(){return承诺解决(“woof”).then(函数(m){expect(m).to.equal('woof');}).catch(函数(m){throw new Error('was not should to fail');});});it('按承诺弹出',function(){return Promise.reject(“呼叫”).then(函数(m){throw new Error('was not should to successed');}).catch(函数(m){expect(m).to.equal('caw');});});
2
  • 6
    第二种方法的问题是抓住预期失败。这给人一种错误的印象,即承诺即使没有实现也会失败。失败的只是期望。 评论 2017年6月8日0:48
  • 谢天谢地,谢谢你告诉我我得打电话Chai.use公司安装它。我从来没有从他们的文档中找到过。|:(
    – 阿西姆
    评论 2017年6月29日3:50
5

我的看法是:

  • 使用异步/等待
  • 不需要额外的chai模块
  • @TheCrazyProgrammer在上面指出,要避免捕获问题

延迟承诺函数,如果延迟为0,则该函数将失败:

const timeoutPromise=(时间)=>{return new Promise((resolve,reject)=>{如果(时间===0)拒绝({“消息”:“无效时间0”})setTimeout(()=>解析('done',time))})}//                     ↓ ↓ ↓it('促进自检',async()=>{//阳性试验let r=等待超时承诺(500)assert.equal(r,“完成”)//阴性试验尝试{等待超时Promise(0)//这里失败的断言是个坏主意,因为它会导致catch子句…}捕获(错误){//可选,检查特定错误(或error.type、error.message以包含…)assert.depEqual(错误,{“消息”:“无效时间0”})return//这很重要}assert.isOk(false,'timeOut must throw')日志('最后')})

阳性试验相当简单。意外故障(由模拟500→0)当拒绝的承诺升级时,测试将自动失败。

阴性试验使用try-catch-idea。然而:只有在catch子句之后才会“抱怨”不需要的传递(这样,它不会以catch()子句结尾,从而触发更多但会误导人的错误。

要使此策略有效,必须从catch子句返回测试。如果不想测试其他内容,请使用另一个it()-block。

1

这是一个更好的解决方案。只需在catch块中返回带有done的错误。

// ...it('失败',(完成)=>{//任何将返回Promise的异步调用ajaxJson({})然后(要求)=>{期望(1)到(11)相等//这将抛出一个错误done()//如果没有错误,这将解决测试问题})捕获((e)=>{完成(e)//这将捕获抛出的错误}); });

此测试将失败,并显示以下消息:AssertionError:应为1等于11

你的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.