Búsqueda de sitios web

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;
});

Artículos relacionados