javascript - Jest simula moment() para devolver una fecha específica
Sé que esta pregunta se ha hecho varias veces.
Pero no pude encontrar el correcto para mi caso.
Me gustaría simular el moment() para que devuelva una fecha específica.
Primero, me burlo de
jest.mock("moment", () => {
return (date: string) =>
jest.requireActual("moment")(date || "2021-01-01T00:00:00.000Z");
});
Pero uso algunas propiedades de moment, (moment.duration()..., por ejemplo) Así que cuando hago un mock así, no funciona.
A continuación intenté simular Date.now de varias maneras:
jest.spyOn(Date, "now").mockReturnValue(+new Date("2021-01-01T00:00:00.000Z"));
Date.now = jest.fn(() => +new Date("2021-01-01T00:00:00.000Z")
Pero al hacer esto, al llamar a moment() devuelve una fecha no válida.
No estoy seguro de lo que estoy haciendo mal.
Respuesta #1
Simula la función moment() y su valor devuelto. Usa jest.requireActual('moment') para obtener el módulo original. Copia sus propiedades y métodos al simulado.
Por ejemplo
index.js:
import moment from 'moment';
export function main() {
const date = moment().format();
console.log('date: ', date);
const duration = moment.duration(2, 'minutes').humanize();
console.log('duration: ', duration);
}
index.test.js:
import { main } from '.';
import moment from 'moment';
jest.mock('moment', () => {
const oMoment = jest.requireActual('moment');
const mm = {
format: jest.fn(),
};
const mMoment = jest.fn(() => mm);
for (let prop in oMoment) {
mMoment[prop] = oMoment[prop];
}
return mMoment;
});
describe('68209029', () => {
it('should pass', () => {
moment().format.mockReturnValueOnce('2021-01-01T00:00:00.000Z');
main();
});
});
resultado de la prueba:
PASS examples/68209029/index.test.js (8.914 s)
68209029
✓ should pass (20 ms)
console.log
date: 2021-01-01T00:00:00.000Z
at Object.main (examples/68209029/index.js:5:11)
console.log
duration: 2 minutes
at Object.main (examples/68209029/index.js:7:11)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.726 s
Echa un vistazo a los registros, simulamos correctamente el valor devuelto de moment().format() y seguimos usando la implementación original del método moment.duration(2, 'minutes').humanize().
Respuesta #2
Además de la respuesta de @slideshowp2.
Solo quería agregar otra manera de esto:
jest.mock("moment", () => {
// Require actual moment
const actualMoment = jest.requireActual("moment");
// Mocking moment func:
// moment() => return specific date, and it won't affect moment(date) with param.
const mockMoment: any = (date: string | undefined) =>
actualMoment(date || "2021-01-01T00:00:00.000Z");
// Now assign all properties from actual moment to the mock moment, so that they can be used normally
for (let prop in actualMoment) {
mockMoment[prop] = actualMoment[prop];
}
return mockMoment;
});
