Callback Async tidak dipanggil dalam batas waktu 5000ms yang ditentukan oleh jest.setTimeout

238

Saya menggunakan dalang dan bercanda untuk menjalankan beberapa tes ujung depan.

Tes saya terlihat sebagai berikut:

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

Terkadang, ketika saya menjalankan tes, semuanya berjalan seperti yang diharapkan. Di waktu lain, saya mendapatkan kesalahan:

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)

Ini aneh karena:

  1. Saya menetapkan batas waktu menjadi 30000

  2. Apakah saya mendapatkan kesalahan ini atau tidak tampaknya sangat acak

Adakah yang bisa menebak mengapa ini terjadi?

Asool
sumber
Baris mana yang kehabisan waktu?
lloyd
@Asool Bisakah Anda memberikan repo GitHub? Akan lebih mudah dan lebih cepat bagi kami untuk memberikan Anda solusi. :)
Shishir Anshuman
@ Asool, umpan balik apa pun atas jawaban yang saya posting
Tarun Lalwani
1
mungkinkah tes tersebut benar-benar gagal untuk 30000 ms tetapi kesalahan dari lelucon hanya tidak termasuk nilai yang Anda lewati? artinya, jika Anda menetapkan waktu 0ms, apakah kesalahan bercanda berubah?
Nirit Levi
Saya melihat kesalahan ini ketika saya sedang men-debug tes saya. Berhenti di breakpoint menyebabkan kesalahan ini
Neets

Jawaban:

259

Jadi batas waktu yang Anda tentukan di sini harus lebih pendek dari batas waktu default.

Batas waktu default adalah 5000dan kerangka kerja secara default adalah jasminedalam kasus jest. Anda dapat menentukan batas waktu di dalam tes dengan menambahkan

jest.setTimeout(30000);

Tapi ini khusus untuk tes. Atau Anda dapat mengatur file konfigurasi untuk 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)

Lihat utas ini juga

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

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

Kesalahan ejaan PS setupFilesAfterEnv(yaitu setupFileAfterEnv) juga akan menimbulkan kesalahan yang sama.

Tarun Lalwani
sumber
2
Terima kasih telah menjawab pertanyaan yang tidak mudah saya temukan melalui dokumentasi Jest.
HartleySan
21
Karena ini membantu saya, mungkin perlu dicatat bahwa setupTestFrameworkScriptFiletelah diganti dengan setupFilesAfterEnv, sehingga menjadisetupFilesAfterEnv: ["./jest.setup.js"]
Maxim Geerinck
1
Saya menemukan juga yang jest.setTimeout(10000)dapat ditambahkan ke satu tes untuk kasus tepi sehingga seluruh konfigurasi tidak perlu berubah :)
James
Aku harus kehilangan sesuatu tapi jika saya menambahkan jest.setTimeout(30000);di jest.config.jssaya mendapatkan "ReferenceError: bercanda tidak didefinisikan". Saya mencoba menambahkan const jest = require("jest");tetapi kemudian saya mendapatkan "TypeError: jest.setTimeout bukan fungsi".
Jean Paul
Ups, saya membaca terlalu cepat: setupFilesAfterEnvargumen di jest.config.jsakan menunjuk ke file lain di mana kami meletakkan jest.setTimeout(30000)opsi. Sangat menyenangkan bahwa kita dapat mengkonfigurasi ini tetapi menurut saya agak rumit.
Jean Paul
64

Itu harus memanggil async/awaitkapan async dari tes.

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);
});
kode schrodinger
sumber
24
Mengapa kita harus memiliki donefungsi async? Bukankah kita hanya mengembalikan Janji atau tidak ditentukan?
Charlie Schliesser
2
Tidak, ini tidak benar. Anda tidak perlu menelepon selesai () karena Anda sedang menunggu janji atau Anda bisa kembali page.click. selesai () digunakan, setidaknya dalam kasus saya, terutama untuk pengujian dengan callback.
Justin
2
Terima kasih teman-teman, saya telah menghapus donepanggilan balik yang tidak diperlukan.
kode
26
bukankah ini kode yang sama dengan pertanyaan aslinya sekarang?
Joe
1
Kehadiran parameter (disebutkan donedalam kasus ini) dalam panggilan balik menyebabkan Jest menunggu hingga parameter ini dipanggil. Kehadirannya signifikan bahkan jika itu tidak digunakan.
Vaughan
54

Jawaban atas pertanyaan ini telah berubah karena Jest telah berevolusi. Jawaban saat ini (Maret 2019):

  1. Anda dapat mengesampingkan batas waktu setiap tes individual dengan menambahkan parameter ketiga ke it. yaitu.it('runs slow', () => {...}, 9999)

  2. Anda dapat mengubah menggunakan standar jest.setTimeout. Untuk melakukan ini:

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

dan

// File: src/jest/defaultTimeout.js
/* global jest */
jest.setTimeout(1000)
  1. Seperti yang dicatat orang lain, dan tidak terkait langsung dengan ini, donetidak perlu dengan pendekatan asink / menunggu.
ndp
sumber
5
ini adalah versi yang lebih modern
jonashdown
23

Saya ingin menambahkan (ini agak lama untuk komentar) yang bahkan dengan batas waktu 3000tes saya masih kadang-kadang (secara acak) gagal dengan

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

Berkat jawaban luar biasa @ Tarun, saya pikir cara terpendek untuk memperbaiki banyak tes adalah:

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

  test('best jest test fest', async () => {
    // blah
  });
});
Roma
sumber
9
Anda tidak perlu menelepon ke jest.setTimeout()dalam beforeEach, menyebutnya sekali sudah cukup untuk semua tes.
Marcos Pereira
19

Ini adalah pembaruan yang relatif baru tetapi jauh lebih lurus ke depan. Jika Anda menggunakan lelucon 24.9.0 atau lebih tinggi Anda bisa menambahkan testTimeoutke konfigurasi Anda:

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

Pastikan untuk melakukan done();panggilan balik atau tidak akan lulus ujian.

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

Berlaku untuk semua fungsi lain yang memiliki callback selesai ().

ZenVentzi
sumber
1
Disebutkan dengan baik, @ ZenVentzi. Terima kasih :)!
ivanleoncz
11

Untuk lelucon 24.9+, Anda juga dapat mengatur batas waktu dari baris perintah dengan menambahkan --testTimeout

Berikut kutipan dari dokumennya

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

Saya baru-baru ini mengalami masalah ini karena alasan yang berbeda: Saya menjalankan beberapa tes secara serentak menggunakan jest -i, dan itu hanya akan kehabisan waktu. Untuk alasan apa pun, menjalankan tes yang sama menggunakan jest --runInBand(meskipun -idimaksudkan untuk menjadi alias) tidak kehabisan waktu.

Mungkin ini akan membantu seseorang ¯\_(:/)_/¯

Jona
sumber
1

Masalah batas waktu terjadi ketika salah satu jaringan lambat atau banyak panggilan jaringan dibuat menggunakan await, skenario ini melebihi batas waktu default yaitu 5000 ms. Untuk menghindari kesalahan batas waktu, cukup tambahkan batas waktu global yang mendukung batas waktu. Daftar global dan tanda tangannya dapat ditemukan di sini .
Untuk Jest 24.9

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

Jika di Jest <= 23:

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

Jika bercanda> 23:

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

Jika seseorang tidak memperbaiki masalah menggunakan metode di atas, saya memperbaiki tambang dengan mengelilingi fungsi async dengan fungsi panah. Seperti dalam:

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
sumber
1
Tampaknya bagi saya bahwa menempatkan fungsi panah di sekitar async tidak akan memberi tahu tes untuk menunggu tes selesai, jadi sementara Anda mungkin tidak mendapatkan kesalahan sekarang, Anda akan memiliki tes yang berjalan di luar utasnya dan a) seluruh rangkaian tes dapat diselesaikan sebelum tes ini dilakukan, tidak menguji kode ini dan b) kesalahan di masa depan dalam tes ini mungkin muncul selama tes yang berbeda di suite, membuat tes Anda rapuh dan sulit dipertahankan.
Mary Shaw
0

Dalam kasus saya, kesalahan ini mulai muncul secara acak dan tidak akan hilang bahkan setelah menetapkan batas waktu 30000. Cukup mengakhiri proses di terminal dan menjalankan kembali tes menyelesaikan masalah untuk saya. Saya juga telah menghapus batas waktu dan tes masih berlalu lagi.

Saurabh Misra
sumber
-2

Di Node ... apa yang saya lihat dilakukan orang sebagai contoh di bawah ini, menggunakan 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
sumber