Wie lege ich ein Scheindatum in Jest fest?

Lesezeit: 6 Minuten

Benutzer-Avatar
Alengel

Ich verwende moment.js, um den größten Teil meiner Datumslogik in einer Hilfsdatei für meine React-Komponenten auszuführen, aber ich konnte nicht herausfinden, wie ich ein Datum in Jest a la verspotten kann sinon.useFakeTimers().

Die Jest-Dokumentation spricht nur über Timer-Funktionen wie setTimeout, setInterval usw. helfen aber nicht beim Einstellen eines Datums und dann beim Überprüfen, ob meine Datumsfunktionen das tun, was sie tun sollen.

Hier ist ein Teil meiner JS-Datei:

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;

und hier ist, was ich mit Jest eingerichtet habe:

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

});

Jetzt werden diese Tests bestanden, weil ich Moment verwende und meine Funktionen Moment verwenden, aber es scheint ein bisschen instabil zu sein, und ich möchte das Datum auf eine feste Zeit für die Tests festlegen.

Irgendeine Idee, wie das bewerkstelligt werden könnte?

  • Können Sie bitte eine andere Antwort auswählen, da Jest jetzt einen eingebauten Datumsspott hat?

    – Mikemaccana

    5. November 2021 um 16:08 Uhr

Benutzer-Avatar
SimenB

Ab Jest 26 kann dies mit “modernen” gefälschten Timern erreicht werden, ohne dass Module von Drittanbietern installiert werden müssen: https://jestjs.io/blog/2020/05/05/jest-26#new-fake-timers

jest
  .useFakeTimers()
  .setSystemTime(new Date('2020-01-01'));

Wenn Sie möchten, dass die gefälschten Timer für aktiv sind alle Tests, die Sie einstellen können timers: 'modern' in deiner Konfiguration: https://jestjs.io/docs/configuration#timers-string

BEARBEITEN: Ab Jest 27 sind moderne gefälschte Timer die Standardeinstellung, sodass Sie das Argument fallen lassen können useFakeTimers.

  • danke Mann, ich denke, das sollte die Lösung dieser Frage sein.

    – Shahzad

    17. August 2020 um 7:26 Uhr

  • Dies ist definitiv die einfachste Lösung für das Problem

    – markyph

    14. Oktober 2020 um 13:25 Uhr

  • Erwähnenswert ist auch die .useFakeTimers('modern') bit kann aus einer globalen Konfigurationsdatei aufgerufen werden (wie z setupTests.js). Damit in einfach entfernt werden kann, ist dies die Standardoption. Aus demselben Link: In Jest 27 we will swap the default to the new "modern".

    – Jose Kilo

    10. November 2020 um 15:56 Uhr

  • Du möchtest vielleicht jest.useRealTimers() nachdem Sie mit den gefälschten Timern fertig sind.

    – Aakash

    21. November 2020 um 9:13 Uhr

  • Diese Lösung funktioniert bei mir nur, wenn ich anrufe jest.setSystemTime() im Testaufbau; wenn ich es anrufe beforeAll meiner Testsuite wird es ignoriert. Überprüfen Sie das von mir erstellte Repo, um dies zu testen github.com/dariospadoni/jestFakeTimersMock/blob/main/src/…

    – Dario

    23. Februar 2021 um 12:00 Uhr


Benutzer-Avatar
stereodenis

Da verwendet momentjs Date intern kannst du die einfach überschreiben Date.now Funktion, um immer denselben Moment zurückzugeben.

Date.now = jest.fn(() => 1487076708000) //14.02.2017

oder

Date.now = jest.fn(() => new Date(Date.UTC(2017, 1, 14)).valueOf())

  • Hier ist eine etwas hübschere Methode zum Festlegen des tatsächlichen Datums, das zurückgegeben wird: Date.now = jest.fn(() => new Date(Date.UTC(2017, 0, 1)).valueOf());

    – entwickeln

    26. Juli 2017 um 16:10 Uhr

  • Oder noch ein bisschen hübscher:Date.now = jest.fn(() => +new Date('2017-01-01');

    – e382df99a7950919789725ceeec126

    30. Juli 2019 um 10:35 Uhr


  • ODER: Date.now = jest.fn(() => Date.parse('2017-02-14))

    – Jeremy Eaton

    8. Januar 2020 um 18:09 Uhr

  • Wird dies alle Verwendungen von richtig verspotten Date? Wie new Date()?

    – Elias Zamaria

    28. August 2020 um 17:28 Uhr

  • @EliasZamaria nein. Diese Antwort deckt diesen Anwendungsfall jedoch ab.

    – Ruluk

    22. September 2021 um 18:04 Uhr


Benutzer-Avatar
Tim Santeford

Für den Quick-and-Dirty-Lösungseinsatz scherz.spyOn für Sperrzeit:

let dateNowSpy;

beforeAll(() => {
    // Lock Time
    dateNowSpy = jest.spyOn(Date, 'now').mockImplementation(() => 1487076708000);
});

afterAll(() => {
    // Unlock Time
    dateNowSpy.mockRestore();
});

AKTUALISIEREN:

Eine robustere Lösung finden Sie unter Zeitnehmer:

import timekeeper from 'timekeeper';

beforeAll(() => {
    // Lock Time
    timekeeper.freeze(new Date('2014-01-01'));
});

afterAll(() => {
    // Unlock Time
    timekeeper.reset();
});

  • Tolle Lösung; keine Abhängigkeiten und die Rücksetzbarkeit machen es einfach, sie auf einen einzelnen Test anzuwenden.

    – Caleb Miller

    15. Februar 2018 um 6:56 Uhr

  • Kein Bedarf für dateNowSpy Variable, und die mockReset() ist überflüssig gem jestjs.io/docs/en/mock-function-api.html#mockfnmockrestore. In dem afterAllkönnen Sie einfach tun Date.now.mockRestore()

    – Jimmy

    17. August 2018 um 19:58 Uhr

  • Das ist großartig, also brauchen Sie keine zusätzlichen Bibliotheken. Dies funktioniert jedoch nur dann wirklich, wenn Sie statische Date-Methoden verwenden (die nicht viele sind).

    – hellatan

    12. Dezember 2018 um 2:09 Uhr

  • @Jimmy Date.now.mockRestore(); gibt ein Die Eigenschaft „mockRestore“ existiert nicht für den Typ „() => Zahl“. Error

    – Marco Lacković

    20. Februar 2019 um 10:28 Uhr

  • @Marco es sollte jest.spyOn(Date, “now”).mockRestore(); sein;

    – sab

    17. April 2019 um 9:32 Uhr

MockDate In Scherztests kann man was ändern new Date() kehrt zurück:

var MockDate = require('mockdate');
// I use a timestamp to make sure the date stays fixed to the ms
MockDate.set(1434319925275);
// test code here
// reset to native Date()
MockDate.reset();

Benutzer-Avatar
RobotEyes

Für diejenigen, die Methoden auf a verspotten wollen new Date Objekt können Sie Folgendes tun:

beforeEach(() => {
    jest.spyOn(Date.prototype, 'getDay').mockReturnValue(2);
    jest.spyOn(Date.prototype, 'toISOString').mockReturnValue('2000-01-01T00:00:00.000Z');
});

afterEach(() => {
    jest.restoreAllMocks()
});

  • Danke, das hat gerade das Problem behoben, das ich hatte.

    – Grayson Langford

    4. Mai 2020 um 20:03 Uhr

Jest-Date-Mock ist ein komplettes Javascript-Modul, das von mir geschrieben wurde, und es wird verwendet, um Date im Scherz zu testen.

import { advanceBy, advanceTo } from 'jest-date-mock';

test('usage', () => {
  advanceTo(new Date(2018, 5, 27, 0, 0, 0)); // reset to date time.

  const now = Date.now();

  advanceBy(3000); // advance time 3 seconds
  expect(+new Date() - now).toBe(3000);

  advanceBy(-1000); // advance time -1 second
  expect(+new Date() - now).toBe(2000);

  clear();
  Date.now(); // will got current timestamp
});

Verwenden Sie die einzigen 3 APIs für Testfälle.

  • advanceBy(ms): Zeitstempel des Datums um ms vorrücken.
  • vorauszu([timestamp]): Datum auf Zeitstempel zurücksetzen, Standard auf 0.
  • clear(): Fährt das Mock-System herunter.

  • Danke, das hat gerade das Problem behoben, das ich hatte.

    – Grayson Langford

    4. Mai 2020 um 20:03 Uhr

Benutzer-Avatar
mattdlockyer

Hier sind ein paar lesbare Möglichkeiten für verschiedene Anwendungsfälle. Ich ziehe es vor, Spione zu verwenden, anstatt Verweise auf die ursprünglichen Objekte zu speichern, die versehentlich in anderem Code überschrieben werden können.

Einmaliger Spott

jest
  .spyOn(global.Date, 'now')
  .mockImplementationOnce(() => Date.parse('2020-02-14'));

Ein paar Tests

let dateSpy;

beforeAll(() => {
  dateSpy = jest
    .spyOn(global.Date, 'now')
    .mockImplementation(() => Date.parse('2020-02-14'));
});

afterAll(() => {
  dateSpy.mockRestore();
});

1309020cookie-checkWie lege ich ein Scheindatum in Jest fest?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy