在调用 beforeEach() 之前异步 beforeAll() 未完成
Async beforeAll() does not finish before beforeEach() is called
在 Jest 中,beforeAll()
应该在 beforeEach()
之前 运行。
问题是,当我为 beforeAll()
使用异步回调时,Jest 在继续 beforeEach()
.
之前不会等待回调完成
如何强制 Jest 在继续 beforeEach()
之前等待异步 beforeAll()
回调完成?
最小的可重现示例
tests/myTest.test.js
const connectToMongo = require('../my_async_callback')
// This uses an async callback.
beforeAll(connectToMongo)
// This is entered before the beforeAll block finishes. =,(
beforeEach(() => {
console.log('entered body of beforeEach')
}
test('t1'), () => {
expect(1).toBe(1)
}
test('t2'), () => {
expect(2+2).toBe(4)
}
test('t3'), () => {
expect(3+3+3).toBe(9)
}
my_async_callback.js
const connectToMongo = async () => {
try {
await mongoose.connect(config.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true
})
console.log('Connected to MongoDB')
} catch (err) {
console.log(`Error connecting to MongoDB: ${err.message}`)
}
}
module.exports = connectToMongo
更新: 正如已接受的答案有用地指出的那样,Jest 实际上会等待 beforeAll
首先完成,除非 Promise 链损坏或暂停。所以,我的问题的前提是错误的。我的 connectToMongo
函数超时,只需增加 Jest 超时即可解决问题。
connectToMongo
函数是一个async函数,不是async callback
(有一个函数作为参数的async函数???)
beforeEach
将在 beforeAll
完成时调用,它仍然有效。
beforeAll(connectToMongo)
将在您调用后立即完成,这意味着它不会等到数据库连接成功。
等到 connectToMongo
完成并继续:
beforeAll(async () => { // async function
await connectToMongo() // wait until connected to db
})
如果有异步函数和回调你可以调用完成。如果你想在异步函数中传递回调你是免费的!
让我告诉你;
beforeAll(async (done) => {
await connectToMongo().catch(done) // if there is error it finish with error payload
done(); // it says i am finish. also you can use it on your callback function to say i am done.
})
The problem is that when I use an async callback for beforeAll()
, Jest doesn't wait for the callback to finish before going on to beforeEach()
.
How can I force Jest to wait for an async beforeAll()
callback to finish before proceeding to beforeEach()
?
TLDR
简短的回答是 Jest 确实 等待异步 beforeAll()
回调完成,然后再继续 beforeEach()
。
这意味着如果 beforeEach()
在 beforeAll()
中应该 运行 的东西之前 运行ning 那么 Promise 链必须被打破或者 beforeAll
功能超时。
Jest 中的队列运行器
与测试相关的所有 beforeAll
、beforeEach
、test
、afterEach
、afterAll
函数都收集在 queueableFns
中并链接 on these lines in queueRunner.ts:
const result = options.queueableFns.reduce(
(promise, fn) => promise.then(() => mapper(fn)),
Promise.resolve(),
);
所以 Jest 从一个已解决的 Promise 开始,并按顺序将每个函数链接到具有 .then
的 Promise 链。
可以通过以下测试看到此行为:
const order = [];
// first beforeAll with async function
beforeAll(async () => {
order.push(1);
await new Promise((resolve) => { setTimeout(resolve, 1000); });
order.push(2);
});
// first beforeEach with done callback
beforeEach(done => {
order.push(4);
setTimeout(() => {
order.push(6);
done();
}, 1000);
order.push(5);
});
// second beforeEach
beforeEach(() => {
order.push(7);
});
// second beforeAll
beforeAll(() => {
order.push(3);
});
it("should run in order", () => {
expect(order).toEqual([1, 2, 3, 4, 5, 6, 7]); // SUCCESS!
});
破碎的承诺链
如果 beforeEach
在 beforeAll
中应该 运行 的东西之前 运行ning 那么 Promise 链可能被破坏了:
const order = [];
// does not return Promise and will break the Promise chain
const func = () => {
setTimeout(() => { order.push(2); }, 1000);
}
const asyncFunc = async () => {
order.push(1);
await func(); // doesn't actually wait for 2 to be pushed
order.push(3);
}
beforeAll(asyncFunc);
beforeEach(() => {
order.push(4);
});
it("should run in order", () => {
expect(order).toEqual([1, 2, 3, 4]); // FAIL: [1, 3, 4]
});
超时
...或者超时(注意Jest会在输出中报告超时):
const order = [];
jest.setTimeout(100); // 100ms timeout
const asyncFunc = async () => {
order.push(1);
await new Promise(resolve => { setTimeout(resolve, 1000); }); // times out
order.push(2);
}
beforeAll(asyncFunc);
beforeEach(() => {
order.push(3);
});
it("should run in order", () => {
expect(order).toEqual([1, 2, 3]); // FAIL: [1, 3] and Timeout error
});
在 Jest 中,beforeAll()
应该在 beforeEach()
之前 运行。
问题是,当我为 beforeAll()
使用异步回调时,Jest 在继续 beforeEach()
.
如何强制 Jest 在继续 beforeEach()
之前等待异步 beforeAll()
回调完成?
最小的可重现示例
tests/myTest.test.js
const connectToMongo = require('../my_async_callback')
// This uses an async callback.
beforeAll(connectToMongo)
// This is entered before the beforeAll block finishes. =,(
beforeEach(() => {
console.log('entered body of beforeEach')
}
test('t1'), () => {
expect(1).toBe(1)
}
test('t2'), () => {
expect(2+2).toBe(4)
}
test('t3'), () => {
expect(3+3+3).toBe(9)
}
my_async_callback.js
const connectToMongo = async () => {
try {
await mongoose.connect(config.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true
})
console.log('Connected to MongoDB')
} catch (err) {
console.log(`Error connecting to MongoDB: ${err.message}`)
}
}
module.exports = connectToMongo
更新: 正如已接受的答案有用地指出的那样,Jest 实际上会等待 beforeAll
首先完成,除非 Promise 链损坏或暂停。所以,我的问题的前提是错误的。我的 connectToMongo
函数超时,只需增加 Jest 超时即可解决问题。
connectToMongo
函数是一个async函数,不是async callback
(有一个函数作为参数的async函数???)
beforeEach
将在 beforeAll
完成时调用,它仍然有效。
beforeAll(connectToMongo)
将在您调用后立即完成,这意味着它不会等到数据库连接成功。
等到 connectToMongo
完成并继续:
beforeAll(async () => { // async function
await connectToMongo() // wait until connected to db
})
如果有异步函数和回调你可以调用完成。如果你想在异步函数中传递回调你是免费的!
让我告诉你;
beforeAll(async (done) => {
await connectToMongo().catch(done) // if there is error it finish with error payload
done(); // it says i am finish. also you can use it on your callback function to say i am done.
})
The problem is that when I use an async callback for
beforeAll()
, Jest doesn't wait for the callback to finish before going on tobeforeEach()
.How can I force Jest to wait for an async
beforeAll()
callback to finish before proceeding tobeforeEach()
?
TLDR
简短的回答是 Jest 确实 等待异步 beforeAll()
回调完成,然后再继续 beforeEach()
。
这意味着如果 beforeEach()
在 beforeAll()
中应该 运行 的东西之前 运行ning 那么 Promise 链必须被打破或者 beforeAll
功能超时。
Jest 中的队列运行器
与测试相关的所有 beforeAll
、beforeEach
、test
、afterEach
、afterAll
函数都收集在 queueableFns
中并链接 on these lines in queueRunner.ts:
const result = options.queueableFns.reduce(
(promise, fn) => promise.then(() => mapper(fn)),
Promise.resolve(),
);
所以 Jest 从一个已解决的 Promise 开始,并按顺序将每个函数链接到具有 .then
的 Promise 链。
可以通过以下测试看到此行为:
const order = [];
// first beforeAll with async function
beforeAll(async () => {
order.push(1);
await new Promise((resolve) => { setTimeout(resolve, 1000); });
order.push(2);
});
// first beforeEach with done callback
beforeEach(done => {
order.push(4);
setTimeout(() => {
order.push(6);
done();
}, 1000);
order.push(5);
});
// second beforeEach
beforeEach(() => {
order.push(7);
});
// second beforeAll
beforeAll(() => {
order.push(3);
});
it("should run in order", () => {
expect(order).toEqual([1, 2, 3, 4, 5, 6, 7]); // SUCCESS!
});
破碎的承诺链
如果 beforeEach
在 beforeAll
中应该 运行 的东西之前 运行ning 那么 Promise 链可能被破坏了:
const order = [];
// does not return Promise and will break the Promise chain
const func = () => {
setTimeout(() => { order.push(2); }, 1000);
}
const asyncFunc = async () => {
order.push(1);
await func(); // doesn't actually wait for 2 to be pushed
order.push(3);
}
beforeAll(asyncFunc);
beforeEach(() => {
order.push(4);
});
it("should run in order", () => {
expect(order).toEqual([1, 2, 3, 4]); // FAIL: [1, 3, 4]
});
超时
...或者超时(注意Jest会在输出中报告超时):
const order = [];
jest.setTimeout(100); // 100ms timeout
const asyncFunc = async () => {
order.push(1);
await new Promise(resolve => { setTimeout(resolve, 1000); }); // times out
order.push(2);
}
beforeAll(asyncFunc);
beforeEach(() => {
order.push(3);
});
it("should run in order", () => {
expect(order).toEqual([1, 2, 3]); // FAIL: [1, 3] and Timeout error
});