Javascript js是否应该导致mocha测试失败

Javascript js是否应该导致mocha测试失败,javascript,unit-testing,mocha.js,should.js,Javascript,Unit Testing,Mocha.js,Should.js,我对单元测试、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:0

我对单元测试、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?任何帮助都将不胜感激。

在测试异步代码时,您需要告诉Mocha测试何时完成(无论测试是否通过)。这是通过为test函数指定一个参数来实现的,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()
的方式就是指定该参数

另外,如果您的承诺有一个“已完成”的处理程序,它在成功和失败时都会触发,那么您也可以在其中调用
done()
,从而保存调用

更多信息,请访问:

更新

在某个时候,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);
        }
    );
});
查看完整的示例

原创

小心。接受的答案只适用于普通异步代码,而不适用于承诺(作者使用的承诺)

不同之处在于,应用程序(在我们的例子中是Mocha)无法捕获从Promise回调抛出的异常,因此测试将通过超时而不是通过实际的断言失败。断言可以记录,也可以不记录,这取决于承诺实现。有关此项的更多信息,请参阅

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

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
函数只用于指定测试是否应该与其他测试同步运行。如果可以,我会加倍投票。将
done
arg传递给测试(
it
的回调函数)的重要性很容易被忽略,但这是造成很多混乱的根源!您忘记添加“done”作为函数的参数