web-dev-qa-db-ja.com

Jestで模擬日付を設定するにはどうすればよいですか?

Moment.jsを使用して、Reactコンポーネントのヘルパーファイルで日付ロジックのほとんどを実行していますが、Jest a la sinon.useFakeTimersで日付をモックする方法を理解できていません。 ()。

Jestのドキュメントは、setTimeout、setInveralなどのタイマー機能についてのみ説明していますが、日付を設定してから、日付機能が意図したとおりに動作するかどうかを確認することはできません。

これが私の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;

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

  });

});

私はモーメントを使用しており、関数はモーメントを使用しているため、これらのテストに合格しましたが、少し不安定なようで、テストの日付を固定時間に設定したいと思います。

それをどのように達成できるかについてのアイデアはありますか?

76
alengel

MockDate は、jestテストでnew Date()が返すものを変更するために使用できます。

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();
50
eadmundo

MomentjsはDateを内部で使用するため、Date.now関数を上書きするだけで、常に同じ瞬間を返すことができます。

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

jest.spyOn はロック時間に対して機能します:

let dateNowSpy;

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

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

jest-date-mock は私が書いた完全なJavaScriptモジュールであり、jestでDateをテストするために使用されます。

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

テストケースには3つのAPIのみを使用します。

  • advanceBy(ms):日付のタイムスタンプをms単位で進めます。
  • advanceTo([timestamp]):日付をタイムスタンプにリセットします。デフォルトは0です。
  • clear():モックシステムをシャットダウンします。
3
atool

一部のパッケージ(たとえばmoment.js)は代わりにDate.now()を使用するため、new Date()のモックのみに基づくすべての答えはどこでも機能しません。

この文脈では、MockDateに基づいた答えは、唯一正しいと思う。外部パッケージを使用したくない場合は、beforeAllに直接書き込むことができます。

  const DATE_TO_USE = new Date('2017-02-02T12:54:59.218Z');
  // eslint-disable-next-line no-underscore-dangle
  const _Date = Date;
  const MockDate = (...args) => {
    switch (args.length) {
      case 0:
        return DATE_TO_USE;
      default:
        return new _Date(...args);
    }
  };
  MockDate.UTC = _Date.UTC;
  MockDate.now = () => DATE_TO_USE.getTime();
  MockDate.parse = _Date.parse;
  MockDate.toString = _Date.toString;
  MockDate.prototype = _Date.prototype;
  global.Date = MockDate;
2
ClementWalter

いくつかの代替アプローチを提供したいと思います。

format()をスタブする必要がある場合(ロケールとタイムゾーンに依存する可能性があります!)

import moment from "moment";
...
jest.mock("moment");
...
const format = jest.fn(() => 'April 11, 2019')
moment.mockReturnValue({ format })

スタブmoment()のみが必要な場合:

import moment from "moment";
...
jest.mock("moment");
...
const now = "moment(\"2019-04-11T09:44:57.299\")";
moment.mockReturnValue(now);

上記のisDateToday関数のテストに関して、momentをモックしないことが最も簡単な方法だと思います

1
Developer Davo

Manual Mocksを使用したいので、すべてのテストで使用できます。

// <rootDir>/__mocks__/moment.js
const moment = jest.requireActual('moment')

Date.now = jest.fn(() => 1558281600000) // 2019-05-20 00:00:00.000+08:00

module.exports = moment
0
codelegant