Асинхронный обратный вызов не был вызван в течение времени ожидания 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. Я получаю эту ошибку, казалось бы, очень случайно

Кто-нибудь может догадаться, почему это происходит?

Asool
источник
Какая линия истекает?
Ллойд
@ Asool Не могли бы вы предоставить репозиторий GitHub? Нам будет проще и быстрее предоставить вам решение. :)
Шишир Аншуман
@ Asool, любые отзывы о ответе, который я разместил
Тарун Лалвани
1
может ли быть так, что тест на самом деле не проходит 30000 мс, но ошибка от jest просто не включает в себя значение, которое вы передали? это означает, что если вы установите 0 мс, изменится ли шутка?
Нирит Леви
Я видел эту ошибку, когда отлаживал свои тесты. Остановка в точке останова привела к получению этой ошибки
Neets

Ответы:

261

Таким образом, указанное вами время ожидания должно быть короче времени ожидания по умолчанию.

Тайм-аут по умолчанию равен, 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.
HartleySan
21
Поскольку это помогло мне, возможно, стоит отметить, что setupTestFrameworkScriptFileоно было заменено setupFilesAfterEnv, поэтому оно становитсяsetupFilesAfterEnv: ["./jest.setup.js"]
Максим
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асинхронную функцию? Разве мы просто не возвращаем Promise или undefined?
Чарли Шлиссер
2
Нет, это не правильно. Вам не нужно вызывать done (), так как вы ожидаете своих обещаний или можете просто вернуться 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 / await.
NDP
источник
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

Это относительно новое обновление, но оно гораздо более простое. Если вы используете Jest 24.9.0 или выше, вы можете просто добавить testTimeoutк своей конфигурации:

// in jest.config.js
module.exports = {
  testTimeout: 30000
}
е-shfiyut
источник
17

Обязательно вызывайте done();обратные вызовы, иначе он просто не пройдет тест.

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

Применяется ко всем другим функциям, которые имеют обратный вызов done ().

ZenVentzi
источник
1
Хорошо упомянуто, @ZenVentzi. Спасибо :)!
ivanleoncz
11

Для jest 24.9+ Вы также можете установить тайм-аут из командной строки, добавив --testTimeout

Вот выдержка из его документации

--testTimeout=<number>
Default timeout of a test in milliseconds. Default value: 5000.
Г-н 14
источник
3

Недавно я столкнулся с этой проблемой по другой причине: я выполнял некоторые тесты синхронно с использованием jest -iвремени ожидания. По каким-то причинам выполнение одних и тех же тестов с использованием jest --runInBand(даже если -iэто псевдоним) не истекает.

Может быть, это кому-то поможет ¯\_(:/)_/¯

Йона
источник
1

Проблема тайм-аута возникает, когда сеть работает медленно или с использованием многих сетевых вызовов await, эти сценарии превышают тайм-аут по умолчанию, т.е. 5000 мс. Чтобы избежать ошибки тайм-аута, просто увеличьте тайм-аут глобалов, которые поддерживают тайм-аут. Список глобалов и их подпись можно найти здесь .
Для шутки 24,9

Neeraj Sewani
источник
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']
}
alexrogers
источник
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);
});
suga_e
источник
1
Мне кажется, что размещение функции стрелки вокруг асинхронного не скажет тесту ждать его завершения, поэтому, хотя вы можете не получить ошибку сейчас, у вас будет тест, запущенный вне его потока и a) весь набор тестов может быть завершен до того, как этот тест будет выполнен, не тестируя этот код, и б) будущие ошибки внутри этого теста могут появиться во время другого теста в наборе, что сделает ваши тесты нестабильными и сложными в обслуживании.
Мэри Шоу
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);
        });
});
WickStargazer
источник