[英]Domains not properly catching errors while testing nodeJS in mocha
当运行利用域进行错误处理的测试时,即使库中的域处理程序应该捕获错误,Mocha仍然会抛出错误。 如果我在Mocha之外执行代码,它的功能正常导致我相信问题是Mocha。
例:
foo.js
module.exports = function(done) {
var domain = require("domain");
var d = domain.create();
d.on("error", function() {
done();
});
d.run(function() {
throw new Error("foo");
});
}
test.js -错误内抛出foo.js
没有被域捕获。
describe("test", function() {
it("should succeed", function(done) {
var foo = require("./foo.js");
foo(function() {
console.log("done");
done();
});
});
});
result : error thrown
script.js - 域正确捕获错误并冒泡。
var foo = require("./foo.js");
foo(function() {
console.log("done");
});
result : done
正如您在上面所看到的,如果我直接指向script.js
它会按照需要运行,域处理程序会捕获错误并继续执行代码。 如果我在Mocha测试中运行相同的代码块,则错误将暂停测试并给出失败。 我相信这是因为错误是在uncaughtException处理程序或类似的东西上发送的。 另一个复杂因素是它在Mocha中正常工作,如果我在函数调用周围有一个process.nextTick(),让我相信Mocha只能处理同步错误,但对异步错误工作得很好。
这里有一些关于这个问题的讨论: https : //groups.google.com/forum/#! msg / nodejs /n- W9BSfxCjI / SElI1DJ_6u0J和https://github.com/joyent/node/issues/4375 。
我的困惑是,所有这些讨论似乎都表明问题已在几个月前得到解决。 任何人都知道这个问题的简单解决方法,或者为什么我没有看到其他人似乎相信的错误已修复此时此问题。
我在Windows 7上的CentOS 6.3 Vagrant VirtualBox上运行节点v0.10.18和Mocha 1.13.0。
发现了问题。 NodeJS域捕获同步错误,但事件继续冒泡到try / catch 。 如果在try/catch
包装domain.run()
,则将执行域错误处理程序和catch。
因此,似乎最好的做法是在所有domain.run()
使用process.nextTick。 这在文档示例中显示,但未按我的意愿明确表达。
例:
d.run(function() {
process.nextTick(function() {
// do stuff
});
});
在这种情况下,缺陷不在摩卡。
在try / catch中没有捕获同步错误的NodeJS域的证明: https : //gist.github.com/owenallenaz/7141699
nodejs域肯定会捕获同步错误
看看这个简单的测试案例
var domain = require("domain");
var d = domain.create();
d.on("error", function() {
console.log("domain caught");
});
d.run(function() {
throw new Error("foo");
});
// result: domain caught
编辑 :自写这个答案以来,我写了一篇博客文章,描述了域名发生了什么,并尝试捕获,以及是否可以使用域名作为try catch的批发替代品。 它总结了这里讨论的大部分内容。
http://www.lighthouselogic.com/node-domains-as-a-replacement-for-try-catch/
原始答案:
实际上Mocha存在问题。
我写了以下测试函数:
function error(callback){
var d = domain.create().on('error', function(err){
console.log("Caught Error in Domain Handler")
return callback(err);
});
d.enter();
throw new Error("TestError");
d.exit();
}
然后我写了一个没有mocha的简单测试:
error(function(err){
if(err)
{
console.log("Error was returned");
}else
{
console.log("Error was not returned")
}
})
我收到的输出是:
Caught Error in Domain Handler
Error was returned
当我使用Mocha测试时:
describe('Domain Tests', function(){
it('Should return an error when testing', function(done){
error(function(err){
if(err)
{
console.log("Error was returned");
}else
{
console.log("Error was not returned")
}
return done();
})
});
});
我收到了以下输出:
․
0 passing (4ms)
1 failing
1) Domain Tests Should return an error when testing:
Error: TestError
at error (/Users/bensudbury/Documents/node_projects/testMochaDomains/test.js:9:11)
at Context.<anonymous> (/Users/bensudbury/Documents/node_projects/testMochaDomains/testMocha.js:6:3)
at Test.Runnable.run (/usr/local/share/npm/lib/node_modules/mocha/lib/runnable.js:194:15)
at Runner.runTest (/usr/local/share/npm/lib/node_modules/mocha/lib/runner.js:358:10)
at /usr/local/share/npm/lib/node_modules/mocha/lib/runner.js:404:12
at next (/usr/local/share/npm/lib/node_modules/mocha/lib/runner.js:284:14)
at /usr/local/share/npm/lib/node_modules/mocha/lib/runner.js:293:7
at next (/usr/local/share/npm/lib/node_modules/mocha/lib/runner.js:237:23)
at Object._onImmediate (/usr/local/share/npm/lib/node_modules/mocha/lib/runner.js:261:5)
at processImmediate [as _immediateCallback] (timers.js:330:15)
如您所见:域错误处理程序被短路了。
此问题似乎与以下问题有关:
https://github.com/visionmedia/mocha/issues/513
虽然Node问题已经关闭,但mocha中的问题仍然存在。
建议的解决方法: https : //gist.github.com/mcollina/4443963在这种情况下无法解决问题。
我挖掘了Mocha的代码并发现问题的出现是因为mocha将测试包装在try catch块中。 这意味着异常被捕获并且永远不会发送到uncaughtException或_fatalException处理程序,具体取决于您使用的节点的版本。
您的解决方法很好,但nodejs域肯定会捕获同步错误,因此我不会更改您的代码,而是更改您的测试。 您的新测试应如下所示:
describe("test", function() {
it("should succeed", function(done) {
process.nextTick(function(){
var foo = require("./foo.js");
foo(function() {
console.log("done");
done();
});
})
});
});
我没有测试过这段代码,但我的示例的类似代码正常工作:
it('Should return an error when testing', function(done){
process.nextTick(function(){
error(function(err){
if(err)
{
console.log("Error was returned");
}else
{
console.log("Error was not returned")
}
return done();
});
})
});
我在Mocha的问题结尾添加了一条评论,看看是否可以解决:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.