Зворотний виклик Async не викликався протягом 5000 мс, визначеного ji.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. Я отримую цю помилку чи ні, здається дуже випадковою

Хтось може здогадатися, чому це відбувається?


Який строк закінчується?
— Ллойд

@Asool Чи можете ви надати репортаж GitHub? Нам буде простіше та швидше запропонувати вам рішення. :)
— Шишир Аншуман

@Asool, будь-які відгуки щодо відповіді, яку я опублікував
— Тарун Лалвані

1
може бути, що тест насправді не спрацьовує за 30000 мс, але помилка від жарту просто не включає значення, яке ви пройшли? значить, якщо ви поставите 0 мс тайм-аут, чи змінюється помилка помилок?
— Ніріт Леві

Я бачив цю помилку, коли налагоджував свої тести. Зупинка на
— точці перерви

Відповіді:


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/isissue/5055

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

Неправильне написання PS setupFilesAfterEnv(тобто setupFileAfterEnv) також призведе до тієї ж помилки.


2
Дякую за відповідь на запитання, яке я не міг легко знайти через документацію Jest.
— HartleySan

21
Оскільки це допомогло мені, можливо, варто зауважити, що його 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 - це не функція".
— Жан Пол

На жаль, я прочитав занадто швидко: setupFilesAfterEnvаргумент в jest.config.jsповинен вказувати на інший файл, де ми ставимо jest.setTimeout(30000)опцію. Приємно, що ми можемо це налаштувати, але мені це здається трохи складним.
— Жан Пол

64

Він повинен викликати те, async/awaitколи він асинхронізований з тесту.

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функцію асинхронізації? Чи не просто ми повернемо Обіцянку чи невизначено?
— Чарлі Шліссер

2
Ні, це не правильно. Вам не потрібно дзвонити виконано (), оскільки ви чекаєте своїх обіцянок або можете просто повернутися page.click. done () використовується, принаймні в моєму випадку, в першу чергу для тестування зворотних викликів.
— Джастін

2
Дякую, хлопці, я видалив doneзворотній дзвінок, який не потрібен.
— код

26
Це не той самий код, як у початковому запитанні зараз?
— Джо

1
Наявність параметра (названого doneв цьому випадку) у зворотному дзвінку змушує Jest чекати, поки цей параметр викликається. Його наявність є важливою, навіть якщо вона не використовується.
— воган

54

Відповідь на це запитання змінилася в міру розвитку Jest. Поточна відповідь (березень 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, зателефонувавши одного разу, достатньо для всіх тестів.
— Маркос Перейра

19

Це відносно нове оновлення, але воно набагато прямо вперед. Якщо ви використовуєте jer 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

Для жарту 24,9+, Ви також можете встановити тайм-аут із командного рядка, додавши --testTimeout

Ось уривок із його документів

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

3

Нещодавно я зіткнувся з цим питанням з іншої причини: я виконував деякі тести синхронно, використовуючи jest -i, і це був би просто час. З будь-яких міркувань, запускайте ті ж тести, використовуючи jest --runInBand(хоча-i це і має бути псевдонім), не закінчується.

Можливо, це комусь допоможе ¯\_(:/)_/¯


1

Проблема з тимчасовим очікуванням виникає, коли будь-яка мережа повільна або використовується багато мережевих дзвінків await, ці сценарії перевищують час очікування за замовчуванням, тобто 5000 мс. Щоб уникнути помилки тайм-ауту, просто збільште тайм-аут глобалістів, які підтримують тайм-аут. Перелік глобалів та їх підпис можна знайти тут .
Для Jest 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

Якщо хтось не виправить проблему з використанням вищевказаних методів, я виправив міну, оточивши функцію асинхронізації функцією стрілки. А саме:

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
Мені здається, що розміщення функції стрілки навколо асинхронізу не дасть тесту зачекати, коли тест завершиться, тому, якщо ви зараз не отримаєте помилку, у вас буде тест, що працює поза його потоком, і а) Весь набір тестів може завершитися до цього тесту, не тестуючи цей код і б) майбутні помилки всередині цього тесту можуть з’явитися під час іншого тесту в наборі, що зробить ваші тести розмитими і важкими у обслуговуванні.
— Мері Шоу

0

У моєму випадку ця помилка почала з’являтися випадковим чином і не зникне навіть після встановлення тайм-ауту 30000. Просто закінчення процесу в терміналі та повторний запуск тестів вирішили проблему для мене. Я також зняв тайм-аут і тести все ще проходять знову.


-2

У Node ... те, що я бачу як приклад, зроблено нижче, використовуючи 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);
        });
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.