【问题标题】:should.js not causing mocha test to failshould.js 不会导致 mocha 测试失败
【发布时间】:2014-06-05 22:51:51
【问题描述】:

我对单元测试、mocha 和 should.js 非常陌生,我正在尝试为返回承诺的异步方法编写测试。这是我的测试代码:

var should = require("should"),
    tideRetriever = require("../tide-retriever"),
    moment = require("moment"),
    timeFormat = "YYYY-MM-DD-HH:mm:ss",
    from = moment("2013-03-06T00:00:00", timeFormat),
    to = moment("2013-03-12T23:59:00", timeFormat),
    expectedCount = 300;

describe("tide retriever", function() {
    it("should retrieve and parse tide CSV data", function() {
        tideRetriever.get(from, to).then(
            function(entries) { // resolve
                entries.should.be.instanceof(Array).and.have.lengthOf(expectedCount);
            },
            function(err) { // reject
                should.fail("Promise rejected", err);
            }
        );
    });
});

当我手动测试 tideRetriever.get 方法时,它始终解析 27 个元素的数组(如预期的那样),但无论 expectedCount 的值如何,测试都不会失败。这是我的简单手动测试:

tideRetriever.get(from, to).then(
    function(entries) {
        console.log(entries, entries.length);
    },
    function(err) {
        console.log("Promise rejected", err);
    }
);

如果有必要,我也可以发布正在测试的模块的源代码。

我对 Mocha 或 should.js 有误解吗?任何帮助将不胜感激。

【问题讨论】:

    标签: javascript unit-testing mocha.js should.js


    【解决方案1】:

    更新

    在某个时候,Mocha 开始支持从测试返回 Promise,而不是添加 done() 回调。原始答案仍然有效,但使用这种方法测试看起来更干净:

    it("should retrieve and parse tide CSV data", function() {
        return tideRetriever.get(from, to).then(
            function(entries) {
                entries.should.be.instanceof(Array).and.have.lengthOf(expectedCount);
            }
        );
    });
    

    查看this gist 获取完整示例。

    原创

    注意。接受的答案仅适用于普通异步代码,不适用于 Promises(作者使用)。

    不同之处在于 Promise 回调抛出的异常不能被应用程序(在我们的例子中为 Mocha)捕获,因此测试将因超时而不是实际断言而失败。根据 Promise 的实现,可以记录或不记录断言。在when documentation 上查看更多信息。

    要使用 Promises 正确处理此问题,您应该将 err 对象传递给 done() 回调而不是抛出它。您可以使用Promise.catch() 方法(不在Promise.then()onRejection() 回调中,因为它不会从同一方法的onFulfilment() 回调中捕获异常)。请参见下面的示例:

    describe("tide retriever", function() {
        it("should retrieve and parse tide CSV data", function(done) {
            tideRetriever.get(from, to).then(
                function(entries) { // resolve
                    entries.should.be.instanceof(Array).and.have.lengthOf(expectedCount);
                    done(); // test passes
                },
                function(err) { // reject
                    done(err); // Promise rejected
                }
            ).catch(function (err) {
                done(err); // should throwed assertion
            });
        });
    });
    

    PS done() 回调在三个地方使用,以涵盖所有可能的情况。但是,如果您不需要其中的任何特殊逻辑,则可以完全删除 onRejection() 回调。在这种情况下,Promise.catch() 也会处理拒绝。

    【讨论】:

    • 您忘记将“done”作为函数的参数添加
    【解决方案2】:

    在测试异步代码时,需要在测试完成时告诉 Mocha(不管是通过还是失败)。这是通过为测试函数指定一个参数来完成的,Mocha 使用done 函数填充该参数。所以你的代码可能看起来像这样:

    describe("tide retriever", function() {
        it("should retrieve and parse tide CSV data", function(done) {
            tideRetriever.get(from, to).then(
                function(entries) { // resolve
                    entries.should.be.instanceof(Array).and.have.lengthOf(expectedCount);
                    done();
                },
                function(err) { // reject
                    should.fail("Promise rejected", err);
                    done();
                }
            );
        });
    });
    

    请注意,Mocha 知道这是一个异步测试的方式,它需要等到 done() 被调用,这只是通过指定该参数。

    另外,如果你的 Promise 有一个“已完成”的处理程序,它会在成功和失败时触发,你也可以在其中调用 done(),从而节省调用。

    更多信息请访问: http://mochajs.github.io/mocha/#asynchronous-code

    【讨论】:

    • 谢谢。我认为done 函数仅用于指定测试是否应与其他测试同步运行。
    • 如果可以的话,我会加倍支持。将done arg 传递给测试(it 的回调函数)的重要性很容易被忽略,但却是很多混乱的根源!
    猜你喜欢
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    • 2012-02-26
    相关资源
    最近更新 更多