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 ハンドラーなどで送信されているためだと思います。もう 1 つの複雑な点は、関数呼び出しの周りに process.nextTick() がある場合、Mocha で適切に機能することです。これにより、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

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();
}

次に、モカなしで簡単なテストを作成しました。

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

ノードの問題はクローズされていますが、モカの問題はまだ開いています。

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 の問題の最後にコメントを追加して、解決できるかどうかを確認しました。

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

于 2013-10-23T23:02:47.023 に答える