การเรียกกลับ Async ไม่ได้ถูกเรียกใช้ภายในการหมดเวลา 5000 มิลลิวินาทีที่ระบุโดย jest.setTimeout


238

ฉันใช้หุ่นกระบอกและล้อเล่นเพื่อทำการทดสอบด้านหน้า

การทดสอบของฉันมีลักษณะดังนี้:

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

บางครั้งเมื่อฉันทำการทดสอบทุกอย่างทำงานตามที่คาดไว้ ในบางครั้งฉันได้รับข้อผิดพลาด:

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)

นี่มันแปลกเพราะ:

  1. ฉันระบุการหมดเวลาเป็น 30000

  2. ฉันได้รับข้อผิดพลาดนี้หรือไม่ดูเหมือนว่าจะสุ่มมาก

ทุกคนสามารถเดาได้ว่าทำไมสิ่งนี้ถึงเกิดขึ้น


เส้นไหนหมดเวลา?
lloyd

@Asool คุณช่วยจัดหา GitHub repo ได้ไหม? มันจะง่ายขึ้นและเร็วขึ้นสำหรับเราในการมอบโซลูชั่นให้กับคุณ :)
Shishir Anshuman

@Asool ข้อเสนอแนะใด ๆ เกี่ยวกับคำตอบที่ฉันโพสต์
Tarun Lalwani

1
เป็นไปได้ไหมที่การทดสอบล้มเหลวในช่วง 30000ms แต่ข้อผิดพลาดจากการล้อเล่นก็ไม่ได้รวมค่าที่คุณผ่าน ความหมายถ้าคุณหมดเวลา 0 มิลลิวินาทีข้อผิดพลาดที่ตลกขบขันจะเปลี่ยนไปหรือไม่
Nirit Levi

ฉันเห็นข้อผิดพลาดนี้เมื่อฉันทำการดีบักการทดสอบ การหยุดที่เบรกพอยต์ทำให้เกิดข้อผิดพลาดนี้
Neets

คำตอบ:


259

ดังนั้นการหมดเวลาที่คุณระบุในที่นี้จะต้องสั้นกว่าการหมดเวลาเริ่มต้น

หมดเวลาการเริ่มต้นคือ5000และกรอบการโดยเริ่มต้นคือในกรณีของjasmine jestคุณสามารถระบุการหมดเวลาในการทดสอบโดยเพิ่ม

jest.setTimeout(30000);

แต่นี่จะเฉพาะเจาะจงสำหรับการทดสอบ หรือคุณสามารถตั้งค่าไฟล์กำหนดค่าสำหรับกรอบงาน

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)

ดูกระทู้นี้ด้วย

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

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

การสะกดคำผิด PS setupFilesAfterEnv(เช่นsetupFileAfterEnv) จะทำให้เกิดข้อผิดพลาดเดียวกัน


2
ขอบคุณที่ตอบคำถามที่ฉันไม่สามารถหาได้ง่ายผ่านทางเอกสาร Jest
Hartley San

21
เช่นนี้ช่วยฉันมันอาจจะเป็นมูลค่า noting ที่setupTestFrameworkScriptFileถูกแทนที่ด้วยsetupFilesAfterEnvดังนั้นมันจึงกลายเป็นsetupFilesAfterEnv: ["./jest.setup.js"]
Maxim Geerinck

1
ผมพบว่ามากเกินไปที่jest.setTimeout(10000)อาจจะเพิ่มการทดสอบเพียงครั้งเดียวสำหรับกรณีที่ขอบเพื่อให้การตั้งค่าทั้งหมดไม่จำเป็นต้องมีการเปลี่ยนแปลง :)
เจมส์

ฉันควรจะพลาดบางอย่าง แต่ถ้าฉันจะเพิ่มjest.setTimeout(30000);ในjest.config.jsฉันจะได้รับ "ReferenceError: ล้อเล่นไม่ได้ถูกกำหนด" ฉันพยายามที่จะเพิ่มconst jest = require("jest");แต่แล้วฉันได้รับ "TypeError: jest.setTimeout ไม่ใช่ฟังก์ชั่น"
Jean Paul

โอ๊ะฉันอ่านเร็วเกินไปsetupFilesAfterEnvอาร์กิวเมนต์jest.config.jsจะชี้ไปยังไฟล์อื่นที่เราใส่jest.setTimeout(30000)ตัวเลือกไว้ เป็นเรื่องที่ดีที่เราสามารถกำหนดค่านี้ได้ แต่ดูเหมือนว่าฉันจะซับซ้อนเล็กน้อย
Jean Paul

64

มันควรจะเรียกasync/awaitเมื่อมันเป็น async จากการทดสอบ

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
ทำไมเราต้องdoneมีฟังก์ชั่น async? เราไม่เพียงแค่คืนสัญญาหรือไม่ได้กำหนดไว้ใช่ไหม
Charlie Schliesser

2
ไม่ไม่ถูกต้อง คุณไม่จำเป็นต้องโทรเสร็จ () เนื่องจากคุณกำลังรอคำสัญญาของคุณหรือคุณสามารถส่งคืนpage.clickได้ done () ใช้อย่างน้อยในกรณีของฉันเป็นหลักสำหรับการทดสอบกับการเรียกกลับ
Justin

2
ขอบคุณพวกฉันได้ลบการdoneติดต่อกลับซึ่งไม่จำเป็น
รหัสของ

26
นี่ไม่ใช่รหัสเดียวกันกับคำถามเดิมใช่ไหม
Joe

1
การปรากฏตัวของพารามิเตอร์ (ชื่อdoneในกรณีนี้) ในการโทรกลับทำให้ Jest รอจนกว่าพารามิเตอร์นี้จะเรียกว่า การปรากฏตัวของมันมีความสำคัญแม้ว่าจะไม่ได้ใช้
วอน

54

คำตอบของคำถามนี้เปลี่ยนไปเมื่อเจสต์มีวิวัฒนาการ คำตอบปัจจุบัน (มีนาคม 2019):

  1. คุณสามารถแทนที่หมดเวลาของการทดสอบบุคคลใด ๆ itโดยการเพิ่มพารามิเตอร์ที่สามไป กล่าวคือit('runs slow', () => {...}, 9999)

  2. jest.setTimeoutคุณสามารถเปลี่ยนค่าเริ่มต้นโดยใช้ เพื่อทำสิ่งนี้:

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

และ

// File: src/jest/defaultTimeout.js
/* global jest */
jest.setTimeout(1000)
  1. เช่นเดียวกับคนอื่น ๆ ได้ตั้งข้อสังเกตและไม่เกี่ยวข้องโดยตรงกับเรื่องนี้doneไม่จำเป็นต้องใช้วิธีการ async / รอคอย

5
นี่เป็นรุ่นที่ทันสมัยกว่า
jonashdown

23

ฉันต้องการที่จะเพิ่ม (นี่เป็นเวลานานสำหรับความคิดเห็น) ที่แม้จะมีการหมดเวลาของ3000การทดสอบของฉันจะยังคงบางครั้ง (สุ่ม) ล้มเหลวด้วย

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

ต้องขอบคุณคำตอบที่ยอดเยี่ยมของ @ Tarun ฉันคิดว่าวิธีที่สั้นที่สุดในการแก้ไขข้อสอบจำนวนมากคือ:

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

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

9
คุณไม่จำเป็นต้องโทรjest.setTimeout()เข้าไปภายในbeforeEachเรียกมันครั้งเดียวก็เพียงพอสำหรับการทดสอบทั้งหมด
Marcos Pereira

19

นี่คือการอัปเดตที่ค่อนข้างใหม่ แต่มันตรงไปตรงมามากขึ้น หากคุณใช้ jest 24.9.0 หรือสูงกว่าคุณสามารถเพิ่มtestTimeoutการกำหนดค่าของคุณได้:

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

17

ตรวจสอบให้แน่ใจว่าได้เรียกใช้การเรียกdone();กลับหรือไม่ผ่านการทดสอบ

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

ใช้กับฟังก์ชั่นอื่น ๆ ทั้งหมดที่มี () โทรกลับเสร็จสิ้น


1
ได้รับการกล่าวถึงอย่างดี @ZenVentzi ขอบคุณ :)!
ivanleoncz

11

สำหรับ jest 24.9+ คุณยังสามารถตั้งค่าการหมดเวลาจากบรรทัดคำสั่งโดยการเพิ่ม --testTimeout

นี่คือข้อความที่ตัดตอนมาจากเอกสารของมัน

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

3

ฉันเพิ่งพบปัญหานี้ด้วยเหตุผลอื่น: ฉันใช้การทดสอบบางอย่างพร้อมกันโดยใช้jest -iและจะหมดเวลา ไม่ว่าจะด้วยเหตุผลใดก็ตามให้รันการทดสอบเดียวกันโดยใช้jest --runInBand(แม้ว่า-iมีความหมายว่าเป็นนามแฝง) ก็ไม่หมดเวลา

บางทีนี่อาจช่วยใครซักคน ¯\_(:/)_/¯


1

ปัญหาการหมดเวลาเกิดขึ้นเมื่อเครือข่ายช้าหรือการโทรผ่านเครือข่ายจำนวนมากใช้awaitสถานการณ์เหล่านี้เกินระยะเวลาเริ่มต้นที่กำหนดไว้เช่น 5000ms เพื่อหลีกเลี่ยงข้อผิดพลาดการหมดเวลาเพียงเพิ่มการหมดเวลาของ globals ที่สนับสนุนการหมดเวลา รายการ Globals และลายเซ็นของพวกเขาสามารถพบได้ที่นี่
สำหรับตลก 24.9


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

หากอยู่ใน Jest <= 23:

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

หากอยู่ใน Jest> 23:

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


0

ในกรณีที่มีคนไม่สามารถแก้ไขปัญหาการใช้วิธีการข้างต้นฉันแก้ไขของฉันโดยล้อมรอบ async func ด้วยฟังก์ชั่นลูกศร ในขณะที่:

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
ดูเหมือนว่าสำหรับฉันการวางฟังก์ชันลูกศรรอบ ๆ async จะไม่บอกให้การทดสอบรอให้การทดสอบเสร็จสมบูรณ์ดังนั้นในขณะที่คุณอาจไม่ได้รับข้อผิดพลาดในขณะนี้คุณจะมีการทดสอบที่ทำงานนอกเธรดและ a) ชุดทดสอบทั้งหมดอาจเสร็จสิ้นก่อนที่การทดสอบนี้จะเสร็จสิ้นการไม่ทดสอบโค้ดนี้และ b) ข้อผิดพลาดในอนาคตในการทดสอบนี้อาจปรากฏขึ้นระหว่างการทดสอบอื่นในชุดการทดสอบทำให้การทดสอบของคุณไม่สม่ำเสมอและยากต่อการบำรุงรักษา
แมรี่ชอว์

0

ในกรณีของฉันข้อผิดพลาดนี้เริ่มปรากฏขึ้นแบบสุ่มและจะไม่หายไปแม้ว่าจะหมดเวลา 30000 เพียงแค่สิ้นสุดกระบวนการในเทอร์มินัลและการเรียกใช้การทดสอบอีกครั้งช่วยแก้ปัญหาสำหรับฉัน ฉันได้ลบการหมดเวลาและการทดสอบก็ยังคงผ่านไปอีกครั้ง


-2

ในโหนด ... สิ่งที่ฉันเห็นคนทำตามตัวอย่างด้านล่างใช้ 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);
        });
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.