[momentjs] Jest에서 모의 ​​데이트를 어떻게 설정하나요?

내 React 구성 요소에 대한 도우미 파일에서 대부분의 날짜 논리를 수행하기 위해 moment.js를 사용하고 있지만 Jest a la에서 날짜를 조롱하는 방법을 알아낼 수 없었습니다 sinon.useFakeTimers().

Jest 문서는 setTimeout, setInterval등과 같은 타이머 기능에 대해서만 설명 하지만 날짜를 설정 한 다음 내 날짜 함수가 의도 한대로 작동하는지 확인하는 데 도움이되지 않습니다.

다음은 내 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);
    });

  });

});

이제 모멘트를 사용하고 내 함수가 모멘트를 사용하기 때문에 이러한 테스트는 통과했지만 약간 불안정 해 보이며 테스트를 위해 날짜를 고정 시간으로 설정하고 싶습니다.

그것이 어떻게 성취 될 수 있는지에 대한 아이디어가 있습니까?



답변

MockDatejest 테스트에서 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();


답변

momentjs는 Date내부적으로 사용하기 때문에 Date.now항상 같은 순간을 반환하도록 함수를 덮어 쓸 수 있습니다 .

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

또는

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


답변

jest.spyOn 은 잠금 시간에 대해 작동합니다.

let dateNowSpy;

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

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


답변

jest-date-mock 은 내가 작성한 완전한 자바 스크립트 모듈이며, 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 () : 모의 시스템을 종료합니다.

답변

새 Date 객체에 대한 모의 메서드를 원하는 사람들을 위해 다음을 수행 할 수 있습니다.

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

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


답변

의 모의만을 기반으로 한 모든 대답 Date.now()은 일부 패키지 (예 :)가 대신 moment.js사용 하기 때문에 모든 곳에서 작동하지 않습니다 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;


답변

몇 가지 대안을 제시하고 싶습니다.

스텁이 필요한 경우 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전혀