Mocha.js: async 函数破坏了嵌套结构

Mocha.js: async function breaks the nested structure

当使用 mocha 测试异步函数的结果时,await 之后的测试从嵌套结构中弹出,如下面的前 2 个测试:

✓ email
✓ phone
current unit
    fetch data
    ✓ is 5==5

3 passing (10ms)

我们怎样才能使测试出现在适当的位置?

代码:

const chai = require('chai');
chai.should();

describe ("current unit", async () => {    
    describe ("fetch data", async () => {    
        it ("is 5==5", () => { chai.expect(5).to.equal(5); });

        const UserData = await getUserData("UserName");

        it ("email", () => { UserData.email.should.equal("example@g.com"); });
        it ("phone", () => { UserData.phone.should.equal("+1 (800) 123 4567"); });
    });
});

function getUserData(param) { return new Promise(resolve => setTimeout(() => resolve({ email:"example@g.com",phone:"+1 (800) 123 4567" }), 1/*ms*/));}

您需要在测试的异步部分之后调用 done() 函数。这是一个例子:

it ("email", (done) => {
  UserData.email.should.equal("example@g.com");
  done();
});

如果你"convert"你的代码从async/await语法到Promise语法,解释起来会更清楚:

describe("current unit", () => {
  describe("fetch data", () => {
    it("is 5==5", () => { chai.expect(5).to.equal(5); });

    getUserData("UserName")
      .then(UserData => {
        it("email", () => { UserData.email.should.equal("example@g.com"); });
        it("phone", () => { UserData.phone.should.equal("+1 (800) 123 4567"); });
      });
  });
});

如您所见,"fetch data" 仅包括 is 5==5,而 emailphone 规格在另一个范围内(在本例中范围是 free describe) 然后这些规格将出现在顶部。

getUserData 只是 "waits" 1 毫秒,然后你可以看到 emailphone 规格,如果你将值增加到 100 毫秒(或更高)你将不会这些规格,因为 getUserData().then 是一个同步块。

切勿直接在 describe 的正文中调用异步操作,让使用 beforeEach,或将其写在 it 的正文中。

使用beforeEach:

describe("current unit", () => { // remove async keyword, it does not make sense
  let UserData; // define variable
  beforeEach(async () => { // async
    UserData = await getUserData("UserName"); // init
  });

  describe("fetch data", () => { // remove async keyword
    it("is 5==5", () => { chai.expect(5).to.equal(5); });
    it("email", () => { UserData.email.should.equal("example@g.com"); });
    it("phone", () => { UserData.phone.should.equal("+1 (800) 123 4567"); });
  });
});
  current unit
    fetch data
      ✓ is 5==5
      ✓ email
      ✓ phone
  3 passing (357ms)

it块中写入:

describe("current unit", () => { // remove async keyword, it does not make sense
  describe("fetch data", () => { // remove async keyword
    it("is 5==5", () => { chai.expect(5).to.equal(5); });
    it("should return correct email and phone", async () => { // compile into 1 spec
      const UserData = await getUserData("UserName");
      UserData.email.should.equal("example@g.com");
      UserData.phone.should.equal("+1 (800) 123 4567");
    });
  });
});
  current unit
    fetch data
      ✓ is 5==5
      ✓ should return correct email and phone (108ms)
  2 passing (149ms)

这是您使用 before

的测试文件
const chai = require('chai');
chai.should();

describe ("current unit", async () => {    
    describe ("fetch data", async () => {    
        let UserData
        before(async () => {
            UserData = await getUserData("UserName");
        })
        it ("is 5==5", () => { chai.expect(5).to.equal(5); });
        it ("email", () => { UserData.email.should.equal("example@g.com"); });
        it ("phone", () => { UserData.phone.should.equal("+1 (800) 123 4567"); });
    });
});

function getUserData(param) { return new Promise(resolve => setTimeout(() => resolve({ email:"example@g.com",phone:"+1 (800) 123 4567" }), 1/*ms*/));}

这是上述测试的输出

  current unit
    fetch data
      ✓ is 5==5
      ✓ email
      ✓ phone

您可以在 "fetch data" 测试套件

中使用 before 表达式使测试出现在适当的位置