Тестируя функцию, у которой есть обещание и setTimeout, почему она отключена по времени?

0

Вопрос

Я пытаюсь протестировать функцию, которая имеет setTimeout внутри обещание. Однако он продолжает отсчитывать время.

Это и есть функция:

export const sleep = async (duration: number): Promise<void> => {
  await new Promise<void>((resolve) => {
    setTimeout(resolve, duration);
  });

  if (process.env.NODE_ENV === "test") {
    console.log("sleep end");
  }
};

И это мой тест:

import { sleep } from "../../helpers/utils";

console.log = jest.fn();
jest.useFakeTimers();

test("calls sleep with correct argument and calls console.log", async () => {
  const NODE_ENV = "test";
  const SLEEP_DURATION = "100";

  process.env = { ...process.env, NODE_ENV, SLEEP_DURATION };

  const timeoutSpy = jest.spyOn(global, "setTimeout");

  await sleep(+SLEEP_DURATION);

  jest.runAllTimers();

  expect(sleep).toHaveBeenCalledWith(+SLEEP_DURATION);
  expect(timeoutSpy).toHaveBeenCalledWith(+SLEEP_DURATION);
  expect(console.log).toHaveBeenCalledWith("sleep end");
});

Проблема в том, что когда я пытаюсь запустить это, тест завершается неудачно и выдает следующее сообщение:

thrown: "Exceeded timeout of 5000 ms for a test.
    Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

Я пытался jest.setTimeout(10000) что просто приводит к ошибке Exceeded timeout of 10000ms ...

Есть какие-нибудь идеи относительно того, почему это происходит? Или как это исправить?

Спасибо!

javascript jestjs settimeout timeout
2021-11-24 01:41:50
1

Лучший ответ

1

Вот решение, которое приближается к тому, к чему вы стремитесь. Важно отметить, что вы не можете await разрешение обещания с использованием поддельных таймеров, иначе оно никогда не разрешится. Вместо этого вы можете позвонить, чтобы назначить возвращаемое значение sleep функция для переменной, затем запустите таймеры, затем дождитесь переменной.

Я также скорректировал ваш expect оператор для тайм-аута, так как он принимает два аргумента. Наконец, я удалил ваше ожидание, что sleep вызывается с указанием продолжительности, потому что вы буквально делаете это в тесте, поэтому, похоже, не стоит делать это утверждение.

console.log = jest.fn();
jest.useFakeTimers();

test("calls sleep with correct argument and calls console.log", async () => {
  const NODE_ENV = "test";
  const SLEEP_DURATION = "100";

  process.env = { ...process.env, NODE_ENV, SLEEP_DURATION };

  const timeoutSpy = jest.spyOn(global, "setTimeout");

  const sleepFn = sleep(+SLEEP_DURATION);

  jest.runAllTimers();

  // Now that we ran timers we can await the promise resolving 
  await sleepFn;

  // timeout takes two arguments
  expect(timeoutSpy).toHaveBeenCalledWith(
    expect.any(Function),
    +SLEEP_DURATION
  );
  expect(console.log).toHaveBeenCalledWith("sleep end");
});
2021-11-24 02:03:50

Спасибо за ваш информативный ответ, я впервые использую эти шутливые таймеры, так что мне определенно нужно немного поучиться!
ffx292

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................