mocha done()和async await的矛盾问题

时间:2017-09-14 10:43:46

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

我有以下测试用例:

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

运行它断言:

  

错误:分辨率方法过分指定。指定回调   回报承诺;不是两个。

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

  

错误:超出2000毫秒超时。对于异步测试和挂钩,请确保   "()完成"叫做;如果返回Promise,请确保它已解决。

如何解决这个悖论?

3 个答案:

答案 0 :(得分:10)

您还需要删除done参数,而不仅仅是对它的调用。像Mocha这样的测试框架会查看函数的参数列表(或者至少是它的arity),以了解您是否正在使用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毫秒超时。对于异步测试和挂钩,请确保&#34; done()&#34;叫做;如果返回Promise,请确保它已解决。

答案 1 :(得分:0)

从中删除作为参数的工作对我有用!只能使用Expect / should。示例如下:

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); 
}) })

答案 2 :(得分:0)

有时需要在 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();
  });
});