Как сказано в заголовке, у меня возникли трудности с имитацией вызова конструктора 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);
});
});