1

试图加快使用 node.js 和 nodeunit 的速度,但发现 nodeunit 存在问题,test.done()在其中一个测试中没有看到调用。

编码:

// Added for clarity.
var client = require("restify").createJsonClient({
    "version": "*",
    "url": "http://localhost:" + server.Port
});

exports["tests"] = {
    "setUp": function (callback) {
        server.StartServer();
        callback();
    },
    "tearDown": function (callback) {
        callback();
    },
    "CanIHaveSomeTeaPlease?": function (test) {
        test.expect(4);
        client.get("/tea", function (err, req, res, data) {
            test.equal(err.statusCode, 418, "Expected ImATeapot Error.");
            test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit.");
            test.equal(err.restCode, "ImATeapotError");
            test.equal(err.name, "ImATeapotError");
            test.done();
        });
    },

    // Note: I expect this test to fail as it is a copy of the above
    //       test on a different url that doesn't return the ImATeapot
    //       HTTP error. But it doesn't look like it's detecting it
    //       properly.

    "TakeThisInfo": function (test) {
        test.expect(4);
        client.put("/push", {
            "hello": "world"
        }, function (err, req, res, data) {
            test.equal(err.statusCode, 418, "Expected ImATeapot Error.");
            test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit.");
            test.equal(err.restCode, "ImATeapotError");
            test.equal(err.name, "ImATeapotError");
            test.done();
        });
    }
};

输出:

FAILURES: Undone tests (or their setups/teardowns):
- tests - TakeThisInfo

To fix this, make sure all tests call test.done()

我希望这是愚蠢的。

版本:-

Node: 0.10.21
NPM: 1.3.11
Nodeunit: 0.8.2
Grunt-CLI: 0.1.10
Grunt: 0.4.1
4

4 回答 4

3

首先,我不知道你的代码中的“服务器”是什么,但我希望它是异步的,所以在你的 setUp 函数中有更多类似的东西:

function (callback) {
  server.StartServer(function(){
    callback();
  });
}

其次,保持当前 nodeunit在每次测试之后和之前执行 startUp 和 tearDown 函数,所以我怀疑您正在启动服务器 2 次(因为在 tearDown 中您并没有真正关闭它)。

于 2013-11-09T23:06:44.820 回答
2

在过去的几个小时里,我一直在处理这个问题,而很明显的是 nodeunit 无法捕获和显示函数中抛出的异常,这些异常稍后由 IO 或 setTimeout 类型的进程触发。考虑到 JavaScript 的运行方式,这并不奇怪。一旦您确定没有异常,一切都会正常工作,但是如果您的代码中有错误,您将收到“撤消测试”消息,而没有其他任何东西。这是我为解决我的问题所做的(以 restify 路由为例):

function myRoute(req, res, next) {
    try {
        // your code goes here...
    }
    catch (err) {
        // write it to the console (for unit testing)
        console.log(err);
        // pass the error to the next function.
        next(err);
    }
}

一旦我以这种方式理解了问题,就解决了它,因为它变得更加清晰,并且我能够通过所有测试!

于 2014-03-06T08:10:50.170 回答
1

我怀疑你实际上并没有test.done()在第二次测试中打电话。在那里console.log()拨打电话以验证您是否确实在拨打电话。

FWIW,我在下面使用您的测试的简化版本重现了所描述的问题。如果省略on('error', function() {...})处理程序,则第二次测试无法完成。因此,我的理论是您的/push端点在 restify 模块中触发了不同的行为。即,您确定restify 正在使用那里的属性调用您的回调err,还是在做一些不同的事情?...例如,像http.get下面那样发出一个事件。

var http = require('http');

exports.test1 = function (test) {
  test.expect(1);
  http.get({hostname: "www.broofa.com", path: "/"}, function (res) {
    test.equal(res.statusCode, 200, 'got 200');
    test.done();
  });
};

exports.test2 = function (test) {
  test.expect(1);
  http.get({hostname: "www.no-such-domain.com", path: "/"}, function (res) {
    test.equal(res.statusCode, 200, 'got 200');
    test.done();
  }).on('error', function() {
    // Comment line below out to repro the "Undone tests" error
    test.done();
  });
};
于 2013-11-09T14:21:06.637 回答
1

我正在通过在设置中将服务器分叉到它自己的进程中来解决它,然后在拆解中将其杀死。认为问题与正在创建的服务器有关,而不是关闭。感谢@matteofigus。

var cp = null; // child process
exports["tests"] = {
    "setUp": function (callback) {
        cp = fork("./lib/server.js", {"silent": true});
        callback();
    },
    "tearDown": function (callback) {
        cp.kill("SIGHUP");
        callback();
    },
    "CanIHaveSomeTeaPlease?": function (test) {
        test.expect(4);
        client.get("/tea", function (err, req, res, data) {
            test.equal(err.statusCode, 418, "Expected ImATeapot Error.");
            test.equal(err.message, "Want a biscuit?", "Expected to be asked if I want a buscuit.");
            test.equal(err.restCode, "ImATeapotError");
            test.equal(err.name, "ImATeapotError");
            test.done();
        });
    },
    "TakeThisInfo": function (test) {
        test.expect(1);
        client.put("/push", {
            "hello": "world"
        }, function (err, req, res, data) {
            test.ok(false);
            test.done();
        });
    }
};
于 2013-11-11T10:03:18.423 回答