【问题标题】:Paradoxical issue with mocha done() and async awaitmocha done() 和异步等待的矛盾问题
【发布时间】:2018-02-23 07:28:54
【问题描述】:

我有以下测试用例:

it("should pass the test", async function (done) {
        await asyncFunction();
        true.should.eq(true);
        done();
    });

运行它断言:

错误:解决方法被过度指定。指定回调 返回一个承诺;不是两者兼而有之。

如果我删除 done(); 语句,它会断言:

错误:超过 2000 毫秒的超时。对于异步测试和钩子,确保 “完成()”被调用;如果返回一个 Promise,请确保它解析。

如何解决这个悖论?

【问题讨论】:

  • 去掉done();的时候,是不是也去掉了函数中的done参数?
  • 不应该有退货声明吗?我的印象是所有同步功能都需要返回来解决。
  • @ShyamBabu:不,一旦他们等待的最后一个承诺完成,如果没有明确的return,他们就会用undefined 解决。
  • @T.J.Crowder 我刚刚删除了 func 签名中的 done 参数,它正在工作!请重写它作为答案,我会接受。
  • @Alon:大声笑,一旦我向自己证明这是问题所在,我确实在写它。就是现在。 :-)

标签: javascript unit-testing typescript async-await mocha.js


【解决方案1】:

您还需要删除done 参数,而不仅仅是对其的调用。像 Mocha 这样的测试框架会查看函数的参数列表(或至少是它的参数),以了解您使用的是 done 还是类似的。

使用 Mocha 3.5.3,这对我有用(必须将 true.should.be(true) 更改为 assert.ok(true),因为前者会出错):

const assert = require('assert');

function asyncFunction() {
    return new Promise(resolve => {
        setTimeout(resolve, 10);
    });
}

describe('Container', function() {
  describe('Foo', function() {
    it("should pass the test", async function () {
        await asyncFunction();
        assert.ok(true);
    });
  });
});

但是如果我添加done:

describe('Container', function() {
  describe('Foo', function() {
    it("should pass the test", async function (done) {  // <==== Here
        await asyncFunction();
        assert.ok(true);
    });
  });
});

...然后我得到

错误:超过 2000 毫秒的超时。对于异步测试和钩子,确保调用了“done()”;如果返回 Promise,请确保它已解决。

【讨论】:

  • 你救了我,浪费时间寻找解决方案
  • @TJ Crowder 关注它(“应该通过......仍然遇到问题“错误:超过 2000 毫秒的超时。对于异步测试和挂钩,请确保调用“done()”;如果返回一个承诺,确保它得到解决。”
  • @AljohnYamaro - 上面示例中的承诺确实解决了。它等待asyncFunction 返回的promise 解决,然后调用assert.ok(true),然后解决(通过返回)。
  • @T.J.Crowder 我想没有必要,我找到了解决方案。在 package.json 上应该是 "test": "mocha --timeout 60000" 之前是 "test": "mocha" 这就是为什么它说错误:超过 2000 毫秒的超时。对于异步测试和钩子,确保调用了“done()”;如果返回 Promise,请确保它已解决。简而言之,必须延长时间。您的解决方案也有效。谢谢。
  • 祝福你!!!严重地。为此浪费了不知道多少小时
【解决方案2】:

从中删除 done 作为参数对我有用!而是只使用期望/应该。示例如下:

getResponse(unitData, function callBack(unit, error, data){ try {
    return request.post(unit, function (err, resp) {
        if (!err && resp.statusCode === 200) {
            if (resp.body.error) {
                return callback(obj, JSON.stringify(resp.body.error), null); 
            }
            return callback(obj, null, resp); 
        } else {
            if (err == null) {  
                err = { statusCode: resp.statusCode, error: 'Error occured.' };
            }
            return callback(obj, err, null); 
        }
    });
} catch (err) {
    return callback(obj, err, null);
}}

之前:

it('receives successful response', async (done) => { 
const getSomeData = await getResponse(unitData, function callBack(unit, error, data){ 
    expect(data.statusCode).to.be.equal(200); 
    done(); 
}) })

之后(工作):

it('receives successful response', async () => { 
const getSomeData = await getResponse(unitData, function callBack(unit, error, data){
     expect(data.statusCode).to.be.equal(200); 
}) })

【讨论】:

    【解决方案3】:

    有些情况下你需要在 mocha 中使用async/await + done 函数。

    例如,在我的socket.io 单元测试用例之一中,我必须使用异步函数调用 db 函数并测试作为回调函数的套接字事件处理程序:

    context("on INIT_CHAT", ()=> {
      it("should create a room", async (done) => {
        const user = await factory.create("User");
        socket.emit("INIT_CHAT", user);
        
        socket.on("JOIN_CHAT", async (roomId) => {
           const room = await ChatRoom.findByPk(roomId);
           expect(room).to.exist;
           // then I need to close a test case here
           done();
        });
      });
    });
    

    这将导致与 OP 中完全相同的错误:

    错误:解决方法被过度指定。指定回调或返回 Promise;不是两者都有。

    我的解决方法:

    我只是将整个测试代码封装在一个 Promise 生成器中:

    context("on INIT_CHAT", ()=> {
      it("should create a room", async () => {
        const asyncWrapper = () => {
          return new Promise(async (resolve) => {
            const user = await factory.create("User");
            socket.emit("INIT_CHAT", user);
            socket.on("JOIN_CHAT", async (roomId) => {
              const room = await ChatRoom.findByPk(roomId);
              expect(room).to.exist;
              resolve(true);
            });
          });
        });
        await asyncWrapper();
      });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 2018-12-09
      • 2018-08-28
      • 2017-04-01
      • 2018-08-24
      相关资源
      最近更新 更多