【问题标题】:Unable to catch exception from within a supertest app request无法从超测应用请求中捕获异常
【发布时间】:2013-12-24 22:22:02
【问题描述】:

此处显示的代码示例:https://gist.github.com/sebinsua/8118001

(3次失败2次通过,我希望4次失败1次成功。)

如果从普通函数中抛出,则可以使用 mocha 捕获 AssertionErrors,但是一旦从超测试包装的应用程序中调用函数,我就不再能够检测到它们。这很烦人,因为我希望能够将某些断言注入到我的 express 应用程序中,然后我可以对其进行测试。 (我正在测试一个带有副作用的中间件,我想测试一下,如果你能告诉我如何模拟请求和响应对象,这也解决了我的问题。)

因为我可以访问间谍,所以我知道这与无法访问的状态无关。

但是,我注意到 node.js/express.js/supertest 会自动将未捕获的异常转换为响应中的错误消息。也许这就是阻止他们被摩卡测试抓住的原因?

编辑

我刚刚测试了下面的代码,看看这是否是一般的 http.createServer() 问题。它不是。这意味着在 connect、express.js、supertest 或 superagent 级别发生了一些事情。 (顺便说一句,这些 sn-ps 代码只能工作一半...)

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

更新

senchalab 在 /lib/proto.js 的连接的第 192 行是这一切都出错的地方。有一个 try-catch,这会将我的错误传递给下一个中间件,该中间件继续做同样的事情,直到 4-arity 中间件处理它或者没有更多中间件在其中运行一些后备代码以自动打印到屏幕并丢弃异常...

我不知道该怎么做才能让它再次抛出我的错误,除非我能够以某种方式覆盖句柄方法。

【问题讨论】:

    标签: javascript node.js testing mocha.js supertest


    【解决方案1】:

    你问:

    但是,我注意到 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-10
      • 2014-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      相关资源
      最近更新 更多