Estoy usando moment.js para hacer la mayor parte de mi lógica de fecha en un archivo auxiliar para mis componentes de React, pero no he podido averiguar cómo simular una cita en Jest a la sinon.useFakeTimers()
.
Los documentos de Jest solo hablan sobre funciones de temporizador como setTimeout
, setInterval
etc. , pero no ayudan a establecer una fecha y luego verificar que mis funciones de fecha hagan lo que deben hacer.
Aquí hay algunos de mis archivos JS:
var moment = require('moment');
var DateHelper = {
DATE_FORMAT: 'MMMM D',
API_DATE_FORMAT: 'YYYY-MM-DD',
formatDate: function(date) {
return date.format(this.DATE_FORMAT);
},
isDateToday: function(date) {
return this.formatDate(date) === this.formatDate(moment());
}
};
module.exports = DateHelper;
y esto es lo que configuré usando Jest:
jest.dontMock('../../../dashboard/calendar/date-helper')
.dontMock('moment');
describe('DateHelper', function() {
var DateHelper = require('../../../dashboard/calendar/date-helper'),
moment = require('moment'),
DATE_FORMAT = 'MMMM D';
describe('formatDate', function() {
it('should return the date formatted as DATE_FORMAT', function() {
var unformattedDate = moment('2014-05-12T00:00:00.000Z'),
formattedDate = DateHelper.formatDate(unformattedDate);
expect(formattedDate).toEqual('May 12');
});
});
describe('isDateToday', function() {
it('should return true if the passed in date is today', function() {
var today = moment();
expect(DateHelper.isDateToday(today)).toEqual(true);
});
});
});
Ahora estas pruebas pasan porque estoy usando moment y mis funciones usan moment, pero parece un poco inestable y me gustaría establecer la fecha en un tiempo fijo para las pruebas.
¿Alguna idea de cómo se podría lograr?
Date
likevalueOf()
.Dado que momentjs se usa
Date
internamente, puede simplemente sobrescribir laDate.now
función para devolver siempre el mismo momento.o
fuente
Date.now = jest.fn(() => new Date(Date.UTC(2017, 0, 1)).valueOf());
Date.now = jest.fn(() => +new Date('2017-01-01');
Date.now = jest.fn(() => Date.parse('2017-02-14))
jest.spyOn funciona para bloquear el tiempo:
fuente
dateNowSpy
variables, ymockReset()
es redundante de acuerdo con jestjs.io/docs/en/mock-function-api.html#mockfnmockrestore . En elafterAll
, simplemente puede hacerloDate.now.mockRestore()
Date.now.mockRestore();
da una 'mockRestore' propiedad no existe en el tipo '() => número de' errorjest-date-mock es un módulo completo de JavaScript escrito por mí, y se usa para probar Date en jest.
Utilice las únicas 3 api para casos de prueba.
fuente
Para aquellos que quieran simular métodos en un nuevo objeto Date, pueden hacer lo siguiente:
fuente
Toda la respuesta basada solo en la simulación de
Date.now()
no funcionará en todas partes ya que algunos paquetes (por ejemplomoment.js
) usannew Date()
en lugar.En este contexto, la respuesta basada en
MockDate
creo que es la única verdaderamente correcta. Si no desea utilizar un paquete externo, puede escribir directamente en subeforeAll
:fuente
Me gustaría ofrecer algunos enfoques alternativos.
Si necesita stub
format()
(que puede depender de la ubicación y la zona horaria)Si solo necesita talón
moment()
:Con respecto a la prueba para la
isDateToday
función anterior, creo que la forma más sencilla sería no burlarsemoment
en absolutofuente
TypeError: moment.mockReturnValue is not a function
jest.mock("moment")
al mismo nivel que sus declaraciones de importación? De lo contrario, puede verlo en acción en este proyectoAsí es como me burlé de mi
Date.now()
método para establecer el año en 2010 para mi pruebafuente
A continuación, se muestran algunas formas legibles para diferentes casos de uso. Prefiero usar espías en lugar de guardar referencias a los objetos originales, que pueden sobrescribirse accidentalmente en algún otro código.
Burla única
Algunas pruebas
fuente
Me gustaría usar Manual Mocks, para que pueda usarse en todas las pruebas.
fuente
El objetivo es simular el nuevo Date () con una fecha fija donde sea que se use durante la representación del componente con fines de prueba. El uso de bibliotecas será una sobrecarga si lo único que desea es simular el nuevo Date () fn.
La idea es almacenar la fecha global en una variable temporal, simular el dae global y luego, después del uso, reasignar la temperatura a la fecha global.
fuente
Solo quería intervenir aquí ya que ninguna respuesta abordó el problema si desea burlarse del
Date
objeto solo en una suite específica.Puede simularlo usando los métodos de configuración y desmontaje para cada suite, jest docs
¡Espero que esto ayude!
fuente
Puedes usar date-faker . Le permite cambiar la fecha actual relativamente:
fuente
A partir de Jest 26, esto se puede lograr utilizando temporizadores falsos "modernos" sin necesidad de instalar ningún módulo de terceros: https://jestjs.io/blog/2020/05/05/jest-26#new-fake-timers
fuente