Как раз в шутку издеваться над вызовом конструктора - PullRequest
1 голос
/ 03 августа 2020

Как сказано в заголовке, у меня возникли трудности с имитацией вызова конструктора new Date() в Jest. Я издеваюсь над этим вызовом, чтобы убедиться, что мои тесты не сработают, возвращая указанную дату c. Однако, поскольку конструктор даты вызывается дважды в функции, которую я тестирую, второй вызов также имеет имитацию своей реализации, этот второй вызов не следует имитировать.

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

Любая помощь будет большим подспорьем, я исчерпал поиски через Stack Overflow и Jest docs.

Заранее спасибо.

Функция

function getSecondsToTomorrow() {
  // This call needs to be mocked to always return the same date time
  const now = new Date();
  
  // This call should not be mocked
  const tomorrow = new Date(
    now.getFullYear(), 
    now.getMonth(), 
    now.getDate() + 1,
    );

  return Math.round( (tomorrow - now) / 1000);
}

Тесты

describe("getSecondsToTomorrow()", () => {
  let result, mockDate, now;

  beforeAll(() => {
    now = new Date(2020, 7, 3, 23, 0, 0);
    mockDate = jest.spyOn(global, "Date").mockImplementation(() => now);
    result = getSecondsToTomorrow();
  });


  afterAll(() => {
    mockDate.mockRestore();
  });

  it("should return the number of seconds until tomorrow, from the time the function was called", () => {
    // We mock the date to be 2300, so the return should be 1 hour (3600 seconds)
    expect(result).toBe(3600);
  });
});

Обновление

Хотя я до сих пор не нашел точного c ответа на свой вопрос, я нашел обходной путь. А именно, используя метод Jest mockImplementationOnce, я могу имитировать datetime при первом вызове new Date() и передавать любые аргументы при втором вызове как mockImplementation по умолчанию.

describe("getSecondsToTomorrow()", () => {
  let result, mockDate, now, dateClone;

  function setUpDateMock(now) {
    return jest
      .spyOn(global, "Date")
      .mockImplementation((...args) => new dateClone(...args))
      .mockImplementationOnce(() => now)
  }

  beforeAll(() => {
    dateClone = Date;
    now = new Date(2020, 7, 3, 23, 0, 0);
    mockDate = setUpDateMock(now);
    result = getSecondsToTomorrow();
  });

  afterAll(() => {
    mockDate.mockRestore();
  });

  it("should return the number of seconds until tomorrow, from the time the function was called", () => {
    expect(result).toBe(3600);
  });
});
...