La devolución de llamada asincrónica no se invocó dentro del tiempo de espera de 5000 ms especificado por jest.setTimeout

238

Estoy usando titiritero y broma para ejecutar algunas pruebas de front-end.

Mis pruebas se ven de la siguiente manera:

describe("Profile Tab Exists and Clickable: /settings/user", () => {
    test(`Assert that you can click the profile tab`, async () => {
      await page.waitForSelector(PROFILE.TAB);
      await page.click(PROFILE.TAB);
    }, 30000);
});

A veces, cuando ejecuto las pruebas, todo funciona como se esperaba. Otras veces, recibo un error:

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

      at node_modules/jest-jasmine2/build/queue_runner.js:68:21
      at Timeout.callback [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:633:19)

Esto es extraño porque:

  1. Especifiqué que el tiempo de espera sea 30000

  2. Si recibo o no este error es aparentemente muy aleatorio

¿Alguien puede adivinar por qué está sucediendo esto?

Asool
fuente
¿Qué línea está agotando el tiempo de espera?
lloyd
@Asool ¿Podría proporcionar un repositorio de GitHub? Para nosotros será más fácil y rápido brindarle una solución. :)
Shishir Anshuman
@Asool, cualquier comentario sobre la respuesta que
publiqué
1
¿podría ser que la prueba realmente falla para los 30000 ms pero el error de broma simplemente no incluye el valor que pasó? es decir, si pone un tiempo de espera de 0 ms, ¿cambia el error de broma?
Nirit Levi el
Vi este error cuando estaba depurando mis pruebas. Al detenerse en un punto de interrupción se produjo este error
Neets

Respuestas:

261

Por lo tanto, el tiempo de espera que especifique aquí debe ser más corto que el tiempo de espera predeterminado.

El tiempo de espera predeterminado es 5000y el marco por defecto es jasmineen caso de jest. Puede especificar el tiempo de espera dentro de la prueba agregando

jest.setTimeout(30000);

Pero esto sería específico para la prueba. O puede configurar el archivo de configuración para el marco.

https://facebook.github.io/jest/docs/en/configuration.html#setuptestframeworkscriptfile-string

// jest.config.js
module.exports = {
  // setupTestFrameworkScriptFile has been deprecated in
  // favor of setupFilesAfterEnv in jest 24
  setupFilesAfterEnv: ['./jest.setup.js']
}

// jest.setup.js
jest.setTimeout(30000)

Ver este hilo también

https://github.com/facebook/jest/issues/5055

https://github.com/facebook/jest/issues/652

La falta de ortografía de PS setupFilesAfterEnv(es decir setupFileAfterEnv) también arrojará el mismo error.

Tarun Lalwani
fuente
2
Gracias por responder una pregunta que no pude encontrar fácilmente a través de la documentación de Jest.
HartleySan
21
Como esto me ayudó, podría valer la pena señalar que la setupTestFrameworkScriptFileha sustituido por setupFilesAfterEnv, por lo que se conviertesetupFilesAfterEnv: ["./jest.setup.js"]
Maxim Geerinck
1
También descubrí que jest.setTimeout(10000)podría agregarse a una sola prueba para un caso perimetral, por lo que no fue necesario cambiar toda la configuración :)
James
Debería perder algo, pero si añado jest.setTimeout(30000);en el jest.config.jsrecibo "ReferenceError: broma no está definido". Intenté agregar const jest = require("jest");pero luego aparece "TypeError: jest.setTimeout no es una función".
Jean Paul
Vaya, leí demasiado rápido: el setupFilesAfterEnvargumento en jest.config.jsapuntará a otro archivo donde ponemos la jest.setTimeout(30000)opción. Es bueno que podamos configurar esto, pero me parece un poco complicado.
Jean Paul
64

Debería llamar al async/awaitcuando es asíncrono de la prueba.

describe("Profile Tab Exists and Clickable: /settings/user", () => {
    test(`Assert that you can click the profile tab`, async (done) => {
        await page.waitForSelector(PROFILE.TAB);
        await page.click(PROFILE.TAB);
        done();
    }, 30000);
});
código de schrodinger
fuente
24
¿Por qué deberíamos tener doneuna función asíncrona? ¿No simplemente devolvemos Promise o undefined?
Charlie Schliesser
2
No, esto no es correcto. No necesita llamar a done () ya que está esperando sus promesas o simplemente podría regresar page.click. done () se usa, al menos en mi caso, principalmente para probar con devoluciones de llamada.
Justin
2
Gracias chicos, he eliminado la donedevolución de llamada que no es necesaria.
código de schrodinger
26
¿No es este el mismo código que en la pregunta original ahora?
Joe
1
La presencia de un parámetro (nombrado doneen este caso) en la devolución de llamada hace que Jest espere hasta que se llame a este parámetro. Su presencia es significativa incluso si no se usa.
Vaughan
54

La respuesta a esta pregunta ha cambiado a medida que Jest ha evolucionado. Respuesta actual (marzo de 2019):

  1. Puede anular el tiempo de espera de cualquier prueba individual agregando un tercer parámetro al it. es decir.it('runs slow', () => {...}, 9999)

  2. Puede cambiar el valor predeterminado usando jest.setTimeout. Para hacer esto:

 // config
   "setupFilesAfterEnv": [  // NOT setupFiles
     "./src/jest/defaultTimeout.js"
   ],

y

// File: src/jest/defaultTimeout.js
/* global jest */
jest.setTimeout(1000)
  1. Como otros han señalado, y no están directamente relacionados con esto, doneno es necesario con el enfoque asíncrono / espera.
ndp
fuente
55
esta es la versión más moderna
jonashdown
23

Me gustaría agregar (esto es un poco largo para un comentario) que incluso con un tiempo de espera de 3000mis pruebas todavía a veces (al azar) fallaba con

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.

Gracias a la gran respuesta de @ Tarun, creo que la forma más corta de arreglar muchas pruebas es:

describe('puppeteer tests', () => {
  beforeEach(() => {
    jest.setTimeout(10000);
  });

  test('best jest test fest', async () => {
    // blah
  });
});
romano
fuente
99
No necesita llamar al jest.setTimeout()interior beforeEach, llamarlo una vez es suficiente para todas las pruebas.
Marcos Pereira
19

Esta es una actualización relativamente nueva, pero es mucho más sencilla. Si está utilizando jest 24.9.0 o superior, simplemente puede agregar testTimeouta su configuración:

// in jest.config.js
module.exports = {
  testTimeout: 30000
}
e-shfiyut
fuente
17

Asegúrese de invocar done();en devoluciones de llamada o no pasará simplemente la prueba.

beforeAll((done /* call it or remove it*/) => {
  done(); // calling it
});

Se aplica a todas las demás funciones que tienen una devolución de llamada done ().

ZenVentzi
fuente
1
Bien mencionado, @ZenVentzi. Gracias :)!
ivanleoncz
11

Para jest 24.9+, también puede establecer el tiempo de espera desde la línea de comando agregando --testTimeout

Aquí hay un extracto de sus documentos

--testTimeout=<number>
Default timeout of a test in milliseconds. Default value: 5000.
Señor 14
fuente
3

Recientemente me encontré con este problema por una razón diferente: estaba ejecutando algunas pruebas sincrónicamente jest -i, y solo se agotaba el tiempo de espera. Para cualquier razonamiento, ejecutar las mismas pruebas usando jest --runInBand(aunque -iesté destinado a ser un alias) no se agota el tiempo de espera.

Quizás esto ayude a alguien ¯\_(:/)_/¯

Jona
fuente
1

El problema de tiempo de espera se produce cuando la red es lenta o se realizan muchas llamadas de red await, estos escenarios exceden el tiempo de espera predeterminado, es decir, 5000 ms. Para evitar el error de tiempo de espera, simplemente aumente el tiempo de espera de los globales que admiten un tiempo de espera. Puede encontrar una lista de globales y su firma aquí .
Para Jest 24.9

Neeraj Sewani
fuente
1
// in jest.setup.js
jest.setTimeout(30000)

Si en Jest <= 23:

// in jest.config.js
module.exports = {
  setupTestFrameworkScriptFile: './jest.setup.js'
}

Si en Jest> 23:

// in jest.config.js
module.exports = {
  setupFilesAfterEnv: ['./jest.setup.js']
}
alexrogers
fuente
0

En caso de que alguien no solucione el problema, utilice los métodos anteriores, arreglé el mío rodeando la función asíncrona con una función de flecha. Como en:

describe("Profile Tab Exists and Clickable: /settings/user", () => {
    test(`Assert that you can click the profile tab`, (() => {
      async () => {
        await page.waitForSelector(PROFILE.TAB)
        await page.click(PROFILE.TAB)
      }
    })(), 30000);
});
suga_e
fuente
1
Me parece que colocar la función de flecha alrededor del asíncrono no le indicará a la prueba que espere a que se complete, por lo que si bien es posible que no obtenga un error ahora, tendrá una prueba ejecutándose fuera de su hilo y a) todo el conjunto de pruebas puede completarse antes de que se realice esta prueba, no probar este código yb) los errores futuros dentro de esta prueba pueden aparecer durante una prueba diferente en la suite, haciendo que sus pruebas sean escamosas y difíciles de mantener.
Mary Shaw
0

En mi caso, este error comenzó a aparecer aleatoriamente y no desaparecería incluso después de establecer un tiempo de espera de 30000. Simplemente finalizar el proceso en el terminal y volver a ejecutar las pruebas resolvió el problema por mí. También eliminé el tiempo de espera y las pruebas aún pasan de nuevo.

Saurabh Misra
fuente
-2

En Nodo ... lo que veo que la gente hizo como ejemplo está a continuación, usando fakeEventEmitter

import { EventEmitter } from 'events';
describe('your case', () => {
 let fakeEventEmitter: EventEmitter;
 beforeEach(async () => {
   fakeEventEmitter = new EventEmitter();
   (fakeEventEmitter as any).pid = 123;
 }),
 it('should do something you want to do', done => {
            anAsynchronouseFunction(testOptions, context).subscribe({
                complete: () => {
                    expect(something).toBeTruthy();
                    done();
                }
            });
            fakeEventEmitter.emit('exit', 0);
        });
});
WickStargazer
fuente