En Jest, se supone que beforeAll() se ejecuta antes de beforeEach() .
El problema es que cuando uso una devolución de llamada asíncrona para beforeAll() , Jest no espera a que finalice la devolución de llamada antes de pasar a beforeEach() .
¿Cómo puedo obligar a Jest a esperar a que finalice una devolución de llamada asincrónica beforeAll() antes de proceder a beforeEach() ?
pruebas/miPrueba.prueba.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 ACTUALIZACIÓN: como señala útilmente la respuesta aceptada, Jest en realidad espera a que beforeAll termine primero, excepto en el caso de una cadena de Promesa rota o un tiempo de espera. Entonces, la premisa de mi pregunta es falsa. Mi función connectToMongo estaba agotando el tiempo de espera, y simplemente aumentando el tiempo de espera de Jest se resolvió el problema.
La función connectToMongo es una función asíncrona, no una async callback de llamada asíncrona (función asíncrona con una función como parámetro ???)
beforeEach se llamará cuando beforeAll haya terminado, y todavía funciona bien.
beforeAll(connectToMongo) se realizará justo después de llamarlo, lo que significa que no esperará hasta que la base de datos se conecte correctamente.
Solo espere hasta que connectToMongo y continúe:
beforeAll(async () => { // async function await connectToMongo() // wait until connected to db })Si hay una función asíncrona y una devolución de llamada, puede llamar a hecho. si desea pasar la devolución de llamada dentro de la función asíncrona, ¡eres libre!
Deja que te enseñe;
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. })El problema es que cuando uso una devolución de llamada asíncrona para
beforeAll(), Jest no espera a que finalice la devolución de llamada antes de pasar abeforeEach().¿Cómo puedo obligar a Jest a esperar a que finalice una devolución de llamada asincrónica
beforeAll()antes de proceder abeforeEach()?
La respuesta corta es que Jest espera a que finalice una devolución de llamada asincrónica beforeAll() antes de proceder a beforeEach() .
Esto significa que si beforeEach() se está ejecutando antes que algo que debería ejecutarse beforeAll() , entonces la cadena Promise debe romperse o la función beforeAll se está agotando.
Todas las beforeAll , beforeEach , test , afterEach , afterAll asociadas con una prueba se recopilan en queueableFns y se encadenan en estas líneas en queueRunner.ts :
const result = options.queueableFns.reduce( (promise, fn) => promise.then(() => mapper(fn)), Promise.resolve(), ); Entonces Jest comienza con una Promesa resuelta y encadena cada función, en orden, a la cadena de Promesa con .then .
Este comportamiento se puede ver con la siguiente prueba:
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! }); Si beforeEach se ejecuta antes de algo que debería ejecutarse beforeAll , entonces es posible que la cadena Promise esté rota:
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] });... o hay un tiempo de espera (tenga en cuenta que Jest informará el tiempo de espera en la salida):
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 });