Il callback asincrono non è stato richiamato entro il timeout di 5000 ms specificato da jest.setTimeout


238

Sto usando burattinaio e scherzo per eseguire alcuni test front-end.

I miei test sono i seguenti:

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 volte, quando eseguo i test, tutto funziona come previsto. Altre volte, ricevo un errore:

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)

Questo è strano perché:

  1. Ho specificato che il timeout è 30000

  2. La presenza o meno di questo errore è apparentemente molto casuale

Qualcuno può indovinare perché questo sta accadendo?


Quale linea sta scadendo?
Lloyd,

@Asool Potresti fornire un repository GitHub? Per noi sarà più facile e veloce fornirti una soluzione. :)
Shishir Anshuman,

@Asool, qualsiasi feedback sulla risposta che ho pubblicato
Tarun Lalwani,

1
potrebbe essere che il test fallisca effettivamente per i 30000ms ma l'errore di jest semplicemente non includa il valore che hai passato? significato, se si mette timeout 0ms, l'errore jest cambia?
Nirit Levi,

Ho visto questo errore durante il debug dei miei test. L'arresto a un punto di interruzione ha provocato questo errore
necessario

Risposte:


260

Pertanto, il timeout specificato qui deve essere più breve del timeout predefinito.

Il timeout predefinito è 5000e il framework per impostazione predefinita è jasminein caso di jest. È possibile specificare il timeout all'interno del test aggiungendo

jest.setTimeout(30000);

Ma questo sarebbe specifico per il test. Oppure puoi impostare il file di configurazione per il framework.

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)

Vedi anche questa discussione

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

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

PS errore di ortografia setupFilesAfterEnv(cioè setupFileAfterEnv) genererà anche lo stesso errore.


2
Grazie per aver risposto a una domanda che non sono riuscito a trovare facilmente tramite la documentazione di Jest.
HartleySan

21
Dato che questo mi ha aiutato, potrebbe valere la pena notare che setupTestFrameworkScriptFileè stato sostituito setupFilesAfterEnv, quindi diventasetupFilesAfterEnv: ["./jest.setup.js"]
Maxim Geerinck,

1
Ho scoperto anche che jest.setTimeout(10000)potrebbe essere aggiunto a un singolo test per un caso limite, quindi l'intera configurazione non ha bisogno di cambiare :)
James

Dovrei perdere qualcosa, ma se aggiungo jest.setTimeout(30000);in jest.config.jsottengo "ReferenceError: jest non è definita". Ho provato ad aggiungere const jest = require("jest");ma poi ottengo "TypeError: jest.setTimeout non è una funzione".
Jean Paul,

Oops, ho letto troppo in fretta: l' setupFilesAfterEnvargomento in jest.config.jsdovrebbe puntare a un altro file in cui mettiamo l' jest.setTimeout(30000)opzione. È bello poterlo configurare, ma mi sembra un po 'complicato.
Jean Paul,

64

Dovrebbe chiamare il async/awaitmomento in cui è asincrono dal test.

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);
});

24
Perché dovremmo avere doneuna funzione asincrona? Non restituiamo semplicemente Promessa o non definito?
Charlie Schliesser,

2
No, questo non è corretto. Non è necessario chiamare done () poiché stai aspettando le tue promesse o potresti semplicemente tornare page.click. done () viene utilizzato, almeno nel mio caso, principalmente per i test con callback.
Justin,

2
Grazie ragazzi, ho rimosso il donecallback che non è necessario.
codice di Schrodinger,

26
non è lo stesso codice della domanda originale ora?
Joe,

1
La presenza di un parametro (chiamato donein questo caso) nel callback fa sì che Jest attenda il richiamo di questo parametro. La sua presenza è significativa anche se non viene utilizzata.
vaughan,

54

La risposta a questa domanda è cambiata con l'evoluzione di Jest. Risposta attuale (marzo 2019):

  1. È possibile ignorare il timeout di ogni singolo test aggiungendo un terzo parametro a it. vale a dire.it('runs slow', () => {...}, 9999)

  2. È possibile modificare il valore predefinito utilizzando jest.setTimeout. Per fare questo:

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

e

// File: src/jest/defaultTimeout.js
/* global jest */
jest.setTimeout(1000)
  1. Come altri hanno notato, e non direttamente correlato a questo, donenon è necessario con l'approccio asincrono / attendi.

5
questa è la versione più moderna
jonashdown

23

Vorrei aggiungere (questo è un po 'lungo per un commento) che anche con un timeout dei 3000miei test a volte fallirebbe (in modo casuale) con

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

Grazie alla grande risposta di @ Tarun, penso che il modo più breve per risolvere molti test sia:

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

  test('best jest test fest', async () => {
    // blah
  });
});

9
Non è necessario chiamare jest.setTimeout()all'interno beforeEach, chiamarlo una volta è sufficiente per tutti i test.
Marcos Pereira,

19

Questo è un aggiornamento relativamente nuovo ma è molto più semplice. Se stai usando jest 24.9.0 o versioni successive puoi semplicemente aggiungere testTimeoutalla tua configurazione:

// in jest.config.js
module.exports = {
  testTimeout: 30000
}

17

Assicurati di invocare i done();callback o non supererà semplicemente il test.

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

Si applica a tutte le altre funzioni con callback done ().


1
Ben citato, @ZenVentzi. Grazie :)!
Ivanleoncz,

11

Per jest 24.9+, è inoltre possibile impostare il timeout dalla riga di comando aggiungendo --testTimeout

Ecco un estratto dai suoi documenti

--testTimeout=<number>
Default timeout of a test in milliseconds. Default value: 5000.

3

Di recente ho riscontrato questo problema per un motivo diverso: stavo eseguendo alcuni test in modo sincrono jest -ie il timeout sarebbe scaduto. Per qualsiasi ragionamento, l'esecuzione degli stessi test utilizzando jest --runInBand(anche se -isi intende che sia un alias) non scade.

Forse questo aiuterà qualcuno ¯\_(:/)_/¯


1

Il problema del timeout si verifica quando una delle reti è lenta o vengono effettuate molte chiamate di rete await, questi scenari superano il timeout predefinito, ovvero 5000ms. Per evitare l'errore di timeout è sufficiente aumentare il timeout dei globi che supportano un timeout. Un elenco di globi e la loro firma è disponibile qui .
Per Jest 24.9


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

Se su Jest <= 23:

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

Se su Jest> 23:

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


0

Nel caso in cui qualcuno non risolva il problema usando i metodi sopra, ho risolto il mio circondando la funzione asincrona con una funzione freccia. Come in:

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);
});

1
Mi sembra che mettere la funzione freccia attorno all'asincrono non dirà al test di attendere il completamento del test, quindi mentre potresti non ricevere un errore ora, avrai un test in esecuzione al di fuori del suo thread e a) il l'intera suite di test può essere completata prima di eseguire questo test, non testando questo codice eb) errori futuri all'interno di questo test potrebbero apparire durante un altro test nella suite, rendendo i test traballanti e difficili da mantenere.
Mary Shaw,

0

Nel mio caso, questo errore ha iniziato a comparire in modo casuale e non sarebbe scomparso anche dopo aver impostato un timeout di 30000. Terminare semplicemente il processo nel terminale e rieseguire i test ha risolto il problema per me. Ho anche rimosso il timeout e i test stanno ancora passando di nuovo.


-2

In Node ... quello che vedo fare le persone come esempio è di seguito, 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);
        });
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.