Der asynchrone Rückruf wurde nicht innerhalb des von jest.setTimeout angegebenen Zeitlimits von 5000 ms aufgerufen

234

Ich benutze Puppenspieler und Scherz, um einige Front-End-Tests durchzuführen.

Meine Tests sehen wie folgt aus:

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

Wenn ich die Tests durchführe, funktioniert manchmal alles wie erwartet. In anderen Fällen wird eine Fehlermeldung angezeigt:

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)

Das ist seltsam, weil:

  1. Ich habe das Timeout auf 30000 festgelegt

  2. Ob ich diesen Fehler bekomme oder nicht, scheint sehr zufällig zu sein

Kann jemand erraten, warum dies geschieht?

Asool
quelle
Welche Leitung läuft ab?
Lloyd
@Asool Könnten Sie ein GitHub-Repo bereitstellen? Es wird für uns einfacher und schneller sein, Ihnen eine Lösung anzubieten. :)
Shishir Anshuman
@Asool, Feedback zu der Antwort, die ich gepostet habe
Tarun Lalwani
1
Könnte es sein, dass der Test für die 30000ms tatsächlich fehlschlägt, aber der Fehler aus dem Scherz einfach nicht den Wert enthält, den Sie übergeben haben? Das heißt, wenn Sie eine Zeitüberschreitung von 0 ms setzen, ändert sich der Scherzfehler?
Nirit Levi
Ich habe diesen Fehler beim Debuggen meiner Tests gesehen. An einem Haltepunkt
anhalten

Antworten:

258

Das hier angegebene Zeitlimit muss daher kürzer sein als das Standardzeitlimit.

Das Standardzeitlimit ist 5000und das Framework ist standardmäßig jasmineim Fall von jest. Sie können das Zeitlimit innerhalb des Tests durch Hinzufügen angeben

jest.setTimeout(30000);

Dies wäre jedoch spezifisch für den Test. Oder Sie können die Konfigurationsdatei für das Framework einrichten.

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)

Siehe auch diesen Thread

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

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

PS-Rechtschreibfehler setupFilesAfterEnv(dh setupFileAfterEnv) führen ebenfalls zu demselben Fehler.

Tarun Lalwani
quelle
2
Vielen Dank für die Beantwortung einer Frage, die ich in der Jest-Dokumentation nicht leicht finden konnte.
HartleySan
21
Da dies mir geholfen hat, könnte es erwähnenswert sein, dass das setupTestFrameworkScriptFiledurch ersetzt wurde setupFilesAfterEnv, so wird essetupFilesAfterEnv: ["./jest.setup.js"]
Maxim Geerinck
Ich fand auch, dass jest.setTimeout(10000)dies zu einem einzelnen Test für einen Edge-Fall hinzugefügt werden konnte, sodass die gesamte Konfiguration nicht geändert werden musste :)
James
Ich habe etwas vermissen , aber wenn ich hinzufügen , jest.setTimeout(30000);in jest.config.jserhalte ich „Reference: Scherz ist nicht definiert“. Ich habe versucht hinzuzufügen, const jest = require("jest");aber dann erhalte ich "TypeError: jest.setTimeout ist keine Funktion".
Jean Paul
Hoppla, ich habe zu schnell gelesen: Das setupFilesAfterEnvArgument in jest.config.jssoll auf eine andere Datei verweisen, in die wir die jest.setTimeout(30000)Option einfügen. Es ist schön, dass wir dies konfigurieren können, aber es scheint mir ein bisschen kompliziert zu sein.
Jean Paul
64

Es sollte das aufrufen, async/awaitwenn es vom Test asynchron ist.

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);
});
Schrödingers Code
quelle
24
Warum sollten wir doneeine asynchrone Funktion haben? Geben wir nicht einfach Versprechen oder undefiniert zurück?
Charlie Schliesser
2
Nein, das ist nicht richtig. Sie müssen nicht done () aufrufen, da Sie auf Ihre Versprechen warten oder einfach zurückkehren können page.click. done () wird zumindest in meinem Fall hauptsächlich zum Testen mit Rückrufen verwendet.
Justin
2
Danke Jungs, ich habe den doneRückruf entfernt, der nicht benötigt wird.
Schrödingers Code
26
Ist das nicht der gleiche Code wie in der ursprünglichen Frage?
Joe
1
Das Vorhandensein eines Parameters ( donein diesem Fall benannt) im Rückruf führt dazu, dass Jest wartet, bis dieser Parameter aufgerufen wird. Seine Anwesenheit ist signifikant, auch wenn es nicht verwendet wird.
Vaughan
54

Die Antwort auf diese Frage hat sich geändert, als sich Jest weiterentwickelt hat. Aktuelle Antwort (März 2019):

  1. Sie können das Timeout jedes einzelnen Tests überschreiben, indem Sie dem einen dritten Parameter hinzufügen it. dh.it('runs slow', () => {...}, 9999)

  2. Sie können die Standardeinstellung mit ändern jest.setTimeout. Um dies zu tun:

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

und

// File: src/jest/defaultTimeout.js
/* global jest */
jest.setTimeout(1000)
  1. Wie andere angemerkt haben und nicht direkt damit zusammenhängen, doneist dies beim asynchronen / abwartenden Ansatz nicht erforderlich.
ndp
quelle
5
Dies ist die modernere Version
Jonashdown
23

Ich möchte hinzufügen (dies ist ein bisschen lang für einen Kommentar), dass selbst mit einer Zeitüberschreitung 3000meiner Tests manchmal (zufällig) immer noch mit scheitern würde

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

Dank der großartigen Antwort von @ Tarun denke ich, dass der kürzeste Weg, um viele Tests zu reparieren, ist:

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

  test('best jest test fest', async () => {
    // blah
  });
});
römisch
quelle
9
Sie müssen nicht anrufen müssen jest.setTimeout()innen beforeEach, es einmal Aufruf für alle Tests genug ist.
Marcos Pereira
18

Dies ist ein relativ neues Update, aber es ist viel einfacher. Wenn Sie jest 24.9.0 oder höher verwenden, können Sie einfach testTimeoutzu Ihrer Konfiguration hinzufügen :

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

Stellen Sie sicher, dass Sie done();bei Rückrufen aufrufen, da sonst der Test nicht einfach bestanden wird.

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

Gilt für alle anderen Funktionen, die einen Rückruf von done () haben.

ZenVentzi
quelle
1
Gut erwähnt, @ZenVentzi. Vielen Dank :)!
ivanleoncz
11

Für Scherz 24.9+ können Sie das Zeitlimit auch über die Befehlszeile festlegen, indem Sie hinzufügen --testTimeout

Hier ist ein Auszug aus den Dokumenten

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

Ich bin kürzlich aus einem anderen Grund auf dieses Problem gestoßen: Ich habe einige Tests synchron mit ausgeführt jest -i, und es würde nur eine Zeitüberschreitung auftreten. Aus welchen Gründen auch immer, das Ausführen derselben Tests mit jest --runInBand(obwohl -idies als Alias ​​gedacht ist) ist keine Zeitüberschreitung.

Vielleicht hilft das jemandem ¯\_(:/)_/¯

Jona
quelle
1

Das Timeout-Problem tritt auf, wenn entweder das Netzwerk langsam ist oder viele Netzwerkanrufe verwendet werden await. Diese Szenarien überschreiten das Standard-Timeout, dh 5000 ms. Um den Timeout-Fehler zu vermeiden, erhöhen Sie einfach das Timeout von Globals, die ein Timeout unterstützen. Eine Liste der Globals und ihrer Unterschrift finden Sie hier .
Für Scherz 24.9

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

Wenn auf Scherz <= 23:

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

Wenn auf Scherz> 23:

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

Falls jemand das Problem mit den oben genannten Methoden nicht behebt, habe ich meine behoben, indem ich die asynchrone Funktion mit einer Pfeilfunktion umgeben habe. Wie 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);
});
suga_e
quelle
1
Es scheint mir, dass das Setzen der Pfeilfunktion um den Async-Modus den Test nicht anweist, auf den Abschluss des Tests zu warten. Während Sie jetzt möglicherweise keinen Fehler erhalten, wird ein Test außerhalb des Threads ausgeführt und a) der Die gesamte Testsuite wird möglicherweise abgeschlossen, bevor dieser Test durchgeführt wird, ohne diesen Code zu testen. b) Zukünftige Fehler in diesem Test können während eines anderen Tests in der Suite auftreten, wodurch Ihre Tests schuppig und schwer zu warten sind.
Mary Shaw
0

In meinem Fall trat dieser Fehler zufällig auf und verschwand auch nach dem Festlegen eines Zeitlimits von 30000 nicht. Durch einfaches Beenden des Vorgangs im Terminal und erneutes Ausführen der Tests wurde das Problem für mich behoben. Ich habe auch das Timeout entfernt und die Tests werden immer noch bestanden.

Saurabh Misra
quelle
-2

In Node ... was ich als Beispiel sehe, ist unten mit 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
quelle