Używam momentu.js, aby wykonać większość logiki dat w pliku pomocniczym dla moich komponentów React, ale nie byłem w stanie wymyślić, jak zakpić datę w Jest a la sinon.useFakeTimers()
.
W żartach docs tylko mówić o funkcjach czasowych, takich jak setTimeout
, setInterval
etc, ale nie pomagają z ustawieniem daty i sprawdzeniu, że moim dniu funkcje zrobić co oni oznaczało zrobić.
Oto część mojego pliku 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;
a oto, co skonfigurowałem za pomocą 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);
});
});
});
Teraz te testy przechodzą, ponieważ używam momentu, a moje funkcje używają momentu, ale wydaje się to trochę niestabilne i chciałbym ustawić datę na stały czas dla testów.
Masz jakiś pomysł, jak można to osiągnąć?
Date
takich jakvalueOf()
.Ponieważ momentjs używa
Date
wewnętrznie, możesz po prostu nadpisaćDate.now
funkcję, aby zawsze zwracała ten sam moment.lub
źródło
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 działa na czas blokowania:
źródło
dateNowSpy
zmiennej, amockReset()
zgodnie z jestjs.io/docs/en/mock-function-api.html#mockfnmockrestore jest on zbędny . WafterAll
, możesz po prostu zrobićDate.now.mockRestore()
Date.now.mockRestore();
daje właściwość `` mockRestore '' nie istnieje w przypadku błędu typu '() => number'jest-date-mock to napisany przeze mnie kompletny moduł javascript, który służy do testowania Date on jest.
Użyj tylko 3 interfejsów API dla przypadków testowych.
źródło
Dla tych, którzy chcą mockować metody w nowym obiekcie Date, możesz wykonać następujące czynności:
źródło
Cała odpowiedź oparta tylko na makiecie
Date.now()
nie będzie działać wszędzie, ponieważ niektóre pakiety (na przykładmoment.js
) używająnew Date()
zamiast tego.W tym kontekście odpowiedź, na której oparto
MockDate
, wydaje mi się jedyna prawdziwie poprawna. Jeśli nie chcesz korzystać z zewnętrznego pakietu, możesz napisać bezpośrednio w swoimbeforeAll
:źródło
Chciałbym zaproponować alternatywne podejścia.
Jeśli potrzebujesz odgiąć
format()
(co może zależeć od lokalizacji i strefy czasowej!)Jeśli potrzebujesz tylko odgiąć
moment()
:Jeśli chodzi o test dla
isDateToday
funkcji powyżej, uważam, że najprostszym sposobem nie byłoby do makietymoment
w ogóleźródło
TypeError: moment.mockReturnValue is not a function
jest.mock("moment")
na tym samym poziomie co instrukcje importu? W przeciwnym razie możesz zobaczyć to w akcji w tym projekcieW ten sposób kpiłem z mojej
Date.now()
metody ustawiania roku na rok 2010 dla mojego testuźródło
Oto kilka czytelnych sposobów dla różnych przypadków użycia. Wolę używać szpiegów niż zapisywać odniesienia do oryginalnych obiektów, które mogą zostać przypadkowo nadpisane w innym kodzie.
Jednorazowe kpiny
Kilka testów
źródło
Od Jest 26 można to osiągnąć za pomocą „nowoczesnych” fałszywych timerów bez konieczności instalowania jakichkolwiek modułów innych firm: https://jestjs.io/blog/2020/05/05/jest-26#new-fake-timers
źródło
Chciałbym użyć ręcznych makiet, aby można go było używać we wszystkich testach.
źródło
Celem jest mockowanie nowej Date () ze stałą datą, gdziekolwiek jest ona używana podczas renderowania komponentu w celach testowych. Korzystanie z bibliotek będzie narzutem, jeśli jedyną rzeczą, którą chcesz, jest mockowanie nowej Date () fn.
Pomysł polega na przechowywaniu globalnej daty w zmiennej tymczasowej, mockowaniu globalnego dae, a następnie po użyciu ponownie przypisanie temp do daty globalnej.
źródło
Chciałem się tutaj tylko zabezpieczyć, ponieważ żadna odpowiedź nie rozwiązała problemu, jeśli chcesz kpić z
Date
obiektu tylko w określonym pakiecie.Możesz go kpić, używając metod konfiguracji i usuwania dla każdego pakietu, jest docs
Mam nadzieję że to pomoże!
źródło
Możesz użyć fałszerza daty . Pozwala względnie zmienić aktualną datę:
źródło