我正在修改node.js库以支持真正的异步操作。
我遇到了Mocha和Chai制作这个(类似的)测试通行证的麻烦。
it('should throw an error', function() {
expect(function() {
process.nextTick(function() {
throw new Error('This is my error');
});
}).to.throw(Error);
});
问题是 - 由于nextTick - 错误被抛出it
的范围,除了测试失败之外,Mocha还输出以下内容。
Uncaught Error: This is my error
构建此测试以使其成功的正确方法是什么?
答案 0 :(得分:4)
嗯......在一个成熟的应用程序中,我要做的就是使用像Sinon这样的东西来检查应该抛出错误的方法是否已被调用并且正在抛出。
在无法执行此操作的代码中,以下方法将捕获异常:
var expect = require("chai").expect;
var domain = require("domain");
it('should throw an error', function(done) {
var d = domain.create();
d.on('error', function (err) {
// Exit the current domain.
d.exit();
// We must execute this code at the next tick.
process.nextTick(function () {
console.log(err); // Just to show something on the console.
expect(err instanceof Error).to.be.true;
done();
});
});
d.run(function () {
process.nextTick(function() {
throw new Error('This is my error');
});
});
});
此代码会在d
中创建一个"domain"。域将在其中发生的未捕获异常上发出error
个事件,因此我们在已创建的域(d.run(...)
)内运行测试并等待异常发生(d.on('error', ...
) 。我们检查它是Error
对象。 (在实际测试中,我还会检查错误消息。)当我们完成时,我们调用done()
告诉Mocha异步测试结束。
error
个事件的处理程序调用{{1}}。这样做是为了让Mocha能够正常捕获错误,如果断言(d.exit()
...)失败了。如果我们不退出域,则域将捕获错误。此外,检查本身必须在下一个刻度线上执行,以便在expect(err instanceof Error)
域之外。
d
问题吗?否<!/强>
domain
的文档附带一些关于在运行正在进行的进程(如服务器)时捕获未捕获的异常时关闭操作的警告。然后要做的是清洁可以清洁的东西并尽快退出。 但是,在测试中使用domain
与Mocha已经在做的事情没有区别。 Mocha捕获异步代码中未处理的异常的方法是使用process.on('uncaughtException'
。在捕获未处理的异常Mocha marks时,当前测试失败并继续。然而关于domain
的{{3}}说“不要使用它,使用uncaughtException
而不是。如果您使用它,请在每次未处理的异常后重新启动应用程序! “
Ergo,任何使用domains
时遇到问题的人都不应该首先使用Mocha 。
答案 1 :(得分:0)
您正试图捕获错误函数的异常,该函数是抛出函数的容器。此外,因为函数包含在nextTick中,所以它在不同的堆栈中执行,因此无法捕获异常(不幸的是,这只是一个JS事件)。
请改为尝试:
it ('should throw an error', function (done) {
process.nextTick(function () {
var myFn = function () { throw new Error() };
expect(myFn).to.throw(Error);
// Tell mocha the test is complete
done();
});
});
更新:没有正确的方法来构建此测试以使其通过,因为您无法在此方案中捕获异常。也许更新你的代码以使用回调来处理错误:
function doSomethingUnsafe() {
try {
// Run code here that may cause exceptions...
callback(null, 'Woohoo! No errors!');
} catch (e) {
callback (e, null);
}
}