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
,而 email
、phone
规格在另一个范围内(在本例中范围是 free describe
) 然后这些规格将出现在顶部。
getUserData
只是 "waits" 1 毫秒,然后你可以看到 email
,phone
规格,如果你将值增加到 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
表达式使测试出现在适当的位置
当使用 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
,而 email
、phone
规格在另一个范围内(在本例中范围是 free describe
) 然后这些规格将出现在顶部。
getUserData
只是 "waits" 1 毫秒,然后你可以看到 email
,phone
规格,如果你将值增加到 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
表达式使测试出现在适当的位置