本次测试:
it('returns the correct value', function(done) {
var returnValue = 5;
aPromise.then(function() {
expect(returnValue).to.equal(42);
done();
});
});
这个测试失败了timeout of 2000ms exceeded
而不是断言错误。 我猜这是因为expect()
调用会引发错误,而done()
永远不会被执行,我想知道是否有更好的方法来测试这种代码。
aPromise
是否曾经解决过? 如果没有,除了暂停,别无选择。
@NickHeiner是的,它解决了; 然后expect()
发现returnValue
不是equal(42)
并抛出。
@gurdiga如果出现超时而不是断言错误,你怎么知道它会抛出?
@hallas @NickHeiner这是正在运行的东西: http :
@gurdiga在我看来,你的承诺有自己的错误捕捉。 尝试在您的承诺中添加.catch(done)
,我认为它会按预期工作。
@hallas Wow:_that_ 就是答案! :) aPromise.finally()
似乎非常适合将done
放入:它也需要在承诺解决时调用。 ;)
谢谢!
我觉得我好笨。
我想我终于明白了:当任何承诺的处理函数中出现任何问题时,无论是传递给.then()
、 .catch()
还是.finally()
的函数,错误都是由承诺库处理。 这样,测试运行器永远不会看到真正的错误, done()
永远不会被调用(因为在它抛出断言错误之前的某些东西),因此超时错误就是您从测试运行器中获得的全部。
为了摆脱承诺,我使用setTimeout()
:
it('returns the correct value', function(done) {
var returnValue = 5;
aPromise.then(function() {
setTimeout(function() {
expect(returnValue).to.equal(42);
done();
});
});
});
我发现这是获取正确错误消息和测试运行器行为的唯一方法。
当done
传递给.catch()
或.finally()
,测试在任何情况下都被视为通过,因此如果存在断言错误,您将永远不会看到它们。
我遇到了类似的问题,最终意识到在使用 promise 测试异步函数时不应该使用 done,而应该返回 promise。 所以你应该能够在没有超时的情况下做到这一点,例如:
it('returns the correct value', function() {
var returnValue = 5;
return aPromise.then(function() {
expect(returnValue).to.equal(42);
});
});
我认为这个问题仍然存在。 我遇到了超时问题,无法通过返回承诺来解决,因为我的模块不使用承诺。
it("works", function(done) {
new Something()
.on("eventA", function(result) {
expect(result).to.be.true;
})
.on("eventB", function(result) {
expect(result).to.be.false;
done();
});
});
Promise
似乎有些过分。try
/ catch
似乎也有些过分,更重要的是,会导致Error: done() called multiple times
。想法:
http://staxmanade.com/2015/11/testing-asyncronous-code-with-mochajs-and-es7-async-await/
至于博客文章的建议,我不知道异步函数错误处理,但对于普通承诺来说,try-catch 建议很奇怪:没有 try-catch 的原始承诺尝试几乎是正确的,它只需要使用.catch(done)
而不是使用then
的第二个参数作为done
。 (当然,由于 Mocha 直接支持 promise,您也可以只返回 promise,但对于它的价值...)最初的 promise 示例中的问题不是缺少 try-catch,而是第二个处理程序to then
不会被第一个处理程序抛出的异常调用,而后面的catch
是; 我不知道以这种方式设计 Promise 的理由是什么,但 Promise 就是这样。 此外,如果由于某种原因有多个then
,则只需要一个最终的.catch(done)
,这是处理程序内部的 try-catch 的一个优势点(在事实上, .catch(done)
开始就不那么样板了)。
至于你的API:
.on("error", function(error) {...})
),那么它们将永远不会到达 Mocha,除非您监听它们并且有侦听器调用done
并带有错误(或者,如果侦听器将错误作为其第一个参数传递给侦听器,则仅使用done
与侦听器一起使用,例如.on("error", done)
。大概这也只会需要在每个测试中编写一次,而不是每个事件处理程序编写一次,就像承诺中的.catch(done)
。"end"
/ "drain"
事件来检查是否设置了其他事件中的布尔值。抱歉,我还是不知道你的 API 应该如何报告错误。
是的,到目前为止,我一直依赖于 _when_ 某些事情失败的超时,然后手动挖掘以找出 _how/why_。 幸运的是,事情很少会出问题,但这并不是缺乏更好设计的借口(主要是我自己)。
@stevenvachon :请提前原谅我,但我看不出你的例子有直接的问题。 在你的事件监听器中做出的断言应该由 Mocha 通过uncaughtException
映射处理(除非事件发射器实现捕捉监听器错误并发出error
事件或其他东西,然后仍然很容易解决)。
现在,如果您在幕后的实现使用 Promise,但发出事件而不是公开 Promise,则您的断言确实会被“吃掉”。 我解决这个问题的方法是使用unhandledRejection
。
我通常把它放在一个在我的测试之前运行的设置脚本中:
process.on('unhandledRejection', function (reason)
{
throw reason;
});
注意:这可能需要一些额外的肘部润滑脂才能在浏览器中工作。
我希望看到 Mocha 像uncaughtException
那样支持它,因为这是一个常见的用例; 仅仅因为我使用 Promises 并不意味着我想将它们返回给调用者!
[email protected] 也有同样的问题
it('Convert files into base64', (resolve) => {
let files = Promise.all(promises);
return files
.then(([actual, expected]) => {
assert.equal(actual, expected, 'Files not are equal');
resolve();
})
.catch(error => resolve);
});
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
.catch
是错误的。 error => resolve
等价于function(error) { return resolve }
,这意味着resolve
不会被调用并且错误被忽略。 您想要的是使用错误调用resolve
,即error => resolve(error)
。 当然,传递一个回调函数X
,它简单地调用Y
函数,其参数与调用X
参数相同,相当于仅传递Y
作为回调,所以即使.catch(error => resolve(error))
也可以简化为.catch(resolve)
。 (如果您将它传递给then
,则只需不要直接传递resolve
,因此,需要避免将then
的结果参数传递给resolve
以防止将其视为错误: then(()=>resolve())
而不仅仅是.then(resolve)
;但是由于您使用then
回调进行断言,因此不会出现.)
(此外,惯用地,这里的resolve
可能应该按照done
方式命名,因为它同时处理成功和失败,并根据是否使用参数调用或不是。因此,Mocha 错误消息中的名称。但这可能是一个有争议的问题;请继续阅读。)
但是,在这种情况下,您可以通过仅返回承诺而不使用 test done 参数来进一步简化它,因为 Mocha 将等待承诺成功或失败以指示测试成功或失败(前提是没有 done 参数)测试函数;在两者都使用的情况下的行为仍在散列中):
it('Convert files into base64', () => {
let files = Promise.all(promises);
return files
.then(([actual, expected]) => {
assert.equal(actual, expected, 'Files not are equal');
})
});
@lsphillips对我
我花了一段时间才解决这个问题! 根据以上答案,以下是两个选项:
npm install --save mocha expect.js q
./node_modules/mocha/bin/mocha test.spec.js
// test.spec.js
var $q = require('q');
var expect = require('expect.js');
describe('tests with done', function(){
it('returns the correct value from promise', function(done) {
var returnValue = 5;
var def = $q.defer();
def.promise.then((val) => {
expect(val).to.equal(42);
done();
}).catch(done);
def.resolve(returnValue)
});
})
describe('tests returning promises', function(){
it('returns the correct value from promise', function() {
var returnValue = 5;
var def = $q.defer();
def.resolve(returnValue)
return def.promise.then((val) => {
expect(val).to.equal(42);
});
});
})
tests with done
1) returns the correct value from promise
tests returning promises
2) returns the correct value from promise
0 passing (15ms)
2 failing
1) tests with done returns the correct value from promise:
Error: expected 5 to equal 42
at Assertion.assert (node_modules/expect.js/index.js:96:13)
at Assertion.be.Assertion.equal (node_modules/expect.js/index.js:216:10)
at def.promise.then (tests/test.spec.js:9:24)
at _fulfilled (node_modules/q/q.js:854:54)
at self.promiseDispatch.done (node_modules/q/q.js:883:30)
at Promise.promise.promiseDispatch (node_modules/q/q.js:816:13)
at node_modules/q/q.js:570:49
at runSingle (node_modules/q/q.js:137:13)
at flush (node_modules/q/q.js:125:13)
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)
2) tests returning promises returns the correct value from promise:
Error: expected 5 to equal 42
at Assertion.assert (node_modules/expect.js/index.js:96:13)
at Assertion.be.Assertion.equal (node_modules/expect.js/index.js:216:10)
at def.promise.then (tests/test.spec.js:22:24)
at _fulfilled (node_modules/q/q.js:854:54)
at self.promiseDispatch.done (node_modules/q/q.js:883:30)
at Promise.promise.promiseDispatch (node_modules/q/q.js:816:13)
at node_modules/q/q.js:570:49
at runSingle (node_modules/q/q.js:137:13)
at flush (node_modules/q/q.js:125:13)
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)
@gurdiga感谢您的 setTimeout() 想法! 我有一个类似的问题,但现在我至少可以得到正确的错误消息!
在我的场景中,我使用 Nightmare 进行 end2end 测试。 我的解决方案是使用.catch(done)
。 您可以在其他 catch 回调中调用done(error)
如下例所示。
describe('Clicking in any bad reputation tag', () => {
it('open the bad reputation modal', (done) => {
nightmare
.select('#per-page', '50')
.waitForAjax()
.click('[data-reputation="bad"]')
.evaluate(function() {
return document.querySelector('.vue-modal .ls-modal-title').innerText
})
.then(function(title) {
title.should.equal('Sua segmentação teve uma avaliação ruim!')
done()
})
.catch((error) => {
screenshot(nightmare)
done(error)
})
})
})
@itumoraes有效,但您可以改为这样做:
describe('Clicking in any bad reputation tag', () => {
it('open the bad reputation modal', () => {
return nightmare
.select('#per-page', '50')
.waitForAjax()
.click('[data-reputation="bad"]')
.evaluate(function() {
return document.querySelector('.vue-modal .ls-modal-title').innerText
})
.then(function(title) {
title.should.equal('Sua segmentação teve uma avaliação ruim!')
})
})
})
如果您返回承诺,则无需调用done()
。 请参阅我的博客文章将 Async/Await 与 Mocha、Express 和 Mongoose 结合使用
我使用了下面的脚本,但我得到了相同的超时超过错误。
我的脚本:
描述(“getBillingDetail”,异步函数(){
this.timeout(55000);
it.only("检查给定的有效作业名",异步函数(完成){
this.timeout(55000);
var 结果 = 等待 url.getBillingDetail('12254785565647858');
控制台日志(结果);
assert.equal(result,true);
});
});
错误:超过 55000 毫秒超时。 对于异步测试和钩子,确保调用“done()”; 如果返回 Promise,请确保它已解决。
不要在多个已解决的问题中拼写相同的东西。 不要将完成的回调传递给异步函数。 阅读有关异步测试的文档
@Munter我删除了完成的回调,但这些错误再次发生
看起来你的承诺从未兑现。
最有用的评论
我遇到了类似的问题,最终意识到在使用 promise 测试异步函数时不应该使用 done,而应该返回 promise。 所以你应该能够在没有超时的情况下做到这一点,例如: