4

ここに示すコード例: https://gist.github.com/sebinsua/8118001

(失敗が3回、合格が2回あります。失敗が4回、成功が1回であってほしいです。)

通常の関数からスローされた場合、mocha で AssertionErrors をキャッチすることは可能ですが、関数がスーパーテスト ラップされたアプリ内から呼び出されるとすぐに、それらを検出できなくなります。特定のアサーションをエクスプレスアプリに挿入してテストできるようにしたかったので、これは面倒です。(私の問題を解決するリクエストオブジェクトとレスポンスオブジェクトをモックアップする方法を教えていただければ、テストしたい副作用のあるミドルウェアをテストしています。)

私はスパイにアクセスできるので、アクセスできない状態とは何の関係もないことを知っています。

ただし、node.js/express.js/supertest は、キャッチされなかった例外を応答のエラー メッセージに自動的に変換することに気付きました。おそらく、それが彼らがモカテストに引っかかるのを妨げているのですか?

編集

これが一般的な http.createServer() の問題であるかどうかを確認するために、すぐ下のコードをテストしました。そうではありません。これは、connect、express.js、supertest、または superagent レベルのいずれかで何かが発生していることを意味します。(これらのコード スニペットは、半分の時間しか機能しません...)

var http   = require("http"),
    assert = require('assert');

describe('Really crazy test of assertions', function () {
    it("cannot create a server which throws an assertion error", function (done) {
        var port = Math.floor(Math.random() * 9999) + 1;
        http.createServer(function (req, res) {
            console.log("On the server.");
            throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
            res.end("HEY");
        }).listen(port);

        setTimeout(function () {
            console.log("On the client.");
            http.get('http://localhost:' + port + '/', function (res) {
                console.log("Will I receive the error message on the client's side? No.");
                console.log(res);
            });
            done();
        }, 1000);
    });
});

これは明らかな問題のようです (以下を参照) - AssertionError が赤いテキストで表示されていないことに気付きました (Mocha によってピックアップされた場合のように)。

var http    = require("http"),
    express = require("express"),
    assert  = require('assert');

var app = express();

describe('Really crazy test of assertions', function () {

    it("cannot create a server which throws an assertion error", function (done) {
        var port = Math.floor(Math.random() * 9999) + 1;
        app.get('/', function (req, res) {
            console.log("On the server.");
            throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
            res.end('HEY');
        }).listen(port);

        setTimeout(function () {
            console.log("On the client.");
            http.get('http://localhost:' + port + '/', function (res) {
                console.log("Will I receive the error message on the client's side? No.");
                console.log(res);
            });
            done();
        }, 1000);
    });
});

要するに、私の質問は、A を B のように振る舞わせるにはどうすればよいかということです。

var http    = require("http"),
    express = require("express"),
    assert  = require('assert');

var app = express();

var port = Math.floor(Math.random() * 9999) + 1;
app.get('/', function (req, res) {
    console.log("On the server.");
    throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
    res.send('HEY');
}).listen(8888);

B

var http   = require("http"),
    assert = require('assert');

http.createServer(function (req, res) {
    console.log("On the server.");
    throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
    res.end("HEY");
}).listen(8888);

アップデート

/lib/proto.js にある senchalab の connect の 192 行目は、これがすべてうまくいかない場所です。try-catch があり、これによりエラーが次のミドルウェアに渡され、4 アリティのミドルウェアがそれを処理するか、フォールバック コードを実行して画面に自動的に出力するミドルウェアがなくなるまで、同じことを続けます。そして例外を破棄します...

何らかの方法でハンドルメソッドを上書きできない限り、エラーを再度スローするために何ができるかわかりません。

4

1 に答える 1

2

あなたが尋ねる:

ただし、node.js/express.js/supertest は、キャッチされなかった例外を応答のエラー メッセージに自動的に変換することに気付きました。おそらく、それが彼らがモカテストに引っかかるのを妨げているのですか?

はい、これが HTTP サーバーの既定の動作とほとんど同じです。サーバー ソフトウェアにとって特別な意味を持たない例外は、ステータス 500 応答に変換されます。したがって、サーバーが例外をスローしたことをテストする場合は、この事実を自分で記録して後で使用できます。例えば:

var http    = require("http"),
    express = require("express"),
    assert  = require('assert');

var app = express();

function handler (req, res) {
    throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
    res.end('HEY');
}

describe('Really crazy test of assertions', function () {
    it("cannot create a server which throws an assertion error", function (done) {
        var port = Math.floor(Math.random() * 9999) + 1;
        var caught;
        app.get('/', function catcher() {
            try {
                handler.apply(this, arguments);
            }
            catch (ex) {
                caught = ex;  // Capture it ...
                throw ex;     // ... and rethrow it.
            }
        }).listen(port);

        setTimeout(function () {
            http.get('http://localhost:' + port + '/', function (res) {
                // Act on the caught exception, if it exists.
                // This could be assert.equal or whatever.
                if (caught)
                    throw caught;
                done();
            });
        }, 1000);
    });
});

これは原理を説明するためのものです。関数は、catcherさまざまなテスト全体で機能するように十分に汎用的に設計できます。

于 2013-12-25T02:31:40.553 に答える