4

在运行使用域进行错误处理的测试时,即使库中的域处理程序应该已经捕获了错误,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。

4

2 回答 2

12

发现了问题。NodeJS 域捕获同步错误,但事件继续冒泡到 try/catch。如果将 a 包装domain.run()在 a 中,try/catch则域错误处理程序和 catch 将被执行。

因此,似乎最好的做法是在 all 中使用 process.nextTick domain.run()。这在文档示例中显示,但没有像我希望的那样明确表达。

例子:

d.run(function() {
    process.nextTick(function() {
        // do stuff
    });
});

在这种情况下,缺陷不在 Mocha 中。

NodeJS 域没有在 try/catch 中捕获同步错误的证明:https ://gist.github.com/owenallenaz/7141699

于 2013-10-21T20:21:02.080 回答
4

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 的情况以及是否可以使用域作为 try catch 的批发替代品。它总结了这里讨论的大部分内容。

http://www.lighthouselogic.com/node-domains-as-a-replacement-for-try-catch/

原始答案:

其实摩卡有问题。

我写了以下测试函数:

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 的 issue 末尾添加了一条评论,看看是否可以解决:

https://github.com/visionmedia/mocha/issues/513

于 2013-10-23T23:02:47.023 回答