在 Mocha 中,返回将被拒绝的承诺与调用 done(err) 的效果不同

In Mocha, returning a promise that will be rejected doesn't have the same effect as calling done(err)

mocha 文档状态

Alternately, instead of using the done() callback, you may return a Promise. This is useful if the APIs you are testing return promises instead of taking callbacks

但是在拒绝时,这两种方式似乎有不同的结果:

var Promise = require("bluebird");

describe('failure', function () {
    describe('why2describes', function () {
        it("fails caught", function (done) {
            new Promise(function (resolve, reject) {
                reject(new Error("boom"))
            }).catch(function (err) {
                done(err)
            })
        });

        it("fails return", function (done) {
            return new Promise(function (resolve, reject) {
                reject(new Error("boom"))
            })
        });
    })
});

第一个结果是

Error: boom

第二个结果

Unhandled rejection Error: boom

然后另外声明Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

第二种情况我做错了吗?

Am I doing something wrong with the 2nd case?

是的。两件事。

  1. 当您没有 catch 处理程序附加到 Promise 链时,错误发生在链内,将以拒绝承诺的形式丢失。 Bluebird 通过检测并抛出该错误来确保不会发生类似的事情

    Unhandled rejection Error: boom
    
  2. 在异步情况下,调用done函数是让测试处理器知道当前测试已经完成的方式。在第二种情况下,您永远不会调用 done。因此它会等待默认超时 2000 毫秒,然后由于该错误而导致测试用例失败。

    但是如果你喜欢使用 Promises/your API return 作为 Promise,那么你根本不应该使用 done 函数。您的代码应如下所示

    it("fails return", function () { // no `done` argument here
        return new Promise(function (resolve, reject) {
            // ideally you would be doing all the assertions here
        })
    });
    

    处理基于 Promises 的测试时要注意的另一个重要事项是,您应该 return Promise 对象。