मैं जेस्ट में एक नकली तारीख कैसे निर्धारित करूं?


111

मैं अपने रिएक्ट घटकों के लिए एक हेल्पर फ़ाइल में अपनी अधिकांश डेट लॉजिक करने के लिए moment.js का उपयोग कर रहा हूं, लेकिन मुझे यह पता नहीं चल पाया है कि जेस्ट ला में डेट कैसे मॉक की जाए sinon.useFakeTimers()

जेस्ट डॉक्स केवल टाइमर फ़ंक्शन जैसे आदि के बारे में बोलते हैं setTimeout, setIntervalलेकिन किसी तिथि को सेट करने में मदद नहीं करते हैं और फिर यह जांचते हैं कि मेरे दिनांक फ़ंक्शन वे करने के लिए क्या कर रहे हैं।

यहाँ मेरी जेएस फाइल में से कुछ है:

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

  });

});

अब ये परीक्षण पास हो गए हैं क्योंकि मैं क्षण का उपयोग कर रहा हूं और मेरे कार्य क्षण का उपयोग करते हैं लेकिन यह थोड़ा अस्थिर लगता है और मैं परीक्षणों के लिए निश्चित समय निर्धारित करना चाहूंगा।

कैसे पूरा किया जा सकता है पर कोई विचार?

जवाबों:


70

MockDate का उपयोग जेस्ट टेस्ट में किया जा सकता है ताकि 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();

महान काम किया क्योंकि मैं Dateजैसे अन्य कार्यों का उपयोग कर रहा था valueOf()
रॉबिन ज़िमरमैन

143

चूँकि क्षणिका Dateआंतरिक रूप से उपयोग करती है , आप Date.nowहमेशा उसी क्षण को वापस करने के लिए फ़ंक्शन को अधिलेखित कर सकते हैं।

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

या

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

34
यहां वास्तविक तिथि निर्धारित करने का एक छोटा सा तरीका है जो वापस आ जाएगा:Date.now = jest.fn(() => new Date(Date.UTC(2017, 0, 1)).valueOf());
विकास करना

4
या यहां तक ​​कि थोड़ा Date.now = jest.fn(() => +new Date('2017-01-01');
प्रीतिकर

3
या:Date.now = jest.fn(() => Date.parse('2017-02-14))
जेरेमी ईटन

93

jest.spyOn लॉकिंग टाइम के लिए काम करता है:

let dateNowSpy;

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

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

3
महान समाधान; कोई निर्भरता नहीं है और इसे फिर से रखने योग्य बनाने से एकल परीक्षण के लिए आवेदन करना आसान हो जाता है।
कालेब मिलर

14
dateNowSpyचर की आवश्यकता नहीं है , और यह jestjs.io/docs/en/mock-function-api.html#mockfnmockrestore केmockReset() अनुसार बेमानी है । में , आप बस कर सकते हैंafterAllDate.now.mockRestore()
जिमी

यह बहुत अच्छा है तो आपको किसी अतिरिक्त पुस्तकालय की आवश्यकता नहीं है। लेकिन यह वास्तव में केवल तभी काम करेगा जब आप स्टेटिक डेट मेथड्स का उपयोग कर रहे हैं (जो कि बहुत से नहीं हैं)
2

1
@ जिमी Date.now.mockRestore();एक संपत्ति देता है 'मॉकस्टोर' प्रकार पर मौजूद नहीं है '() => संख्या' त्रुटि
मार्को लैकोविच

3
@ मार्को यह jest.spyOn (दिनांक, "अब") होना चाहिए। mockRestore ();
साब

6

jest-date-mock मेरे द्वारा लिखा गया एक पूरा जावास्क्रिप्ट मॉड्यूल है, और इसका उपयोग jest पर दिनांक का परीक्षण करने के लिए किया जाता है।

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 एपीआई का उपयोग करें।

  • एडवांसबाय (एमएस): एमएस द्वारा अग्रिम तिथि टाइमस्टैम्प।
  • advanceTo ([टाइमस्टैम्प]): टाइमस्टैम्प पर रीसेट की तारीख, 0 के लिए डिफ़ॉल्ट।
  • clear (): mock system को बंद करें।

आपका मामला क्या है?
एटूल

5

उन लोगों के लिए जो नई दिनांक ऑब्जेक्ट पर विधियाँ मॉक करना चाहते हैं, आप निम्न कार्य कर सकते हैं:

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

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

धन्यवाद, यह सिर्फ उस मुद्दे को तय करता है जो मैं कर रहा था।
ग्रेसन लैंगफोर्ड

2

केवल 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;

2

मैं कुछ वैकल्पिक तरीकों की पेशकश करना चाहूंगा।

यदि आपको स्टब करने की आवश्यकता है 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सब पर


2
पहले उदाहरण के लिए, मुझे मिलता हैTypeError: moment.mockReturnValue is not a function
mkelley33

2
क्या jest.mock("moment")आपके आयात विवरण समान स्तर पर हैं? अन्यथा, आप इस परियोजना
डेविड

1

इस तरह मैंने Date.now()अपने परीक्षण के लिए वर्ष 2010 को निर्धारित करने के लिए अपने तरीके का मजाक उड़ाया

jest
  .spyOn(global.Date, 'now')
  .mockImplementationOnce(() => new Date(`2010`).valueOf());

1

विभिन्न उपयोग मामलों के लिए यहां कुछ पठनीय तरीके दिए गए हैं। मैं मूल वस्तुओं के संदर्भों को बचाने के लिए जासूसों का उपयोग करना पसंद करता हूं, जिसे गलती से किसी अन्य कोड में लिखा जा सकता है।

एकबारगी मजाक करना

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

कुछ परीक्षण

let dateSpy;

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

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

0

मैं मैनुअल मोक्स का उपयोग करना चाहता हूं, इसलिए यह सभी परीक्षणों में उपयोग कर सकता है।

// <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

लक्ष्य उद्देश्यों के लिए घटक रेंडरिंग के दौरान जहां भी इसका उपयोग किया जाता है, लक्ष्य एक निश्चित तारीख के साथ नई तिथि () का मजाक उड़ाता है। पुस्तकालयों का उपयोग एक ओवरहेड होगा यदि केवल एक चीज जो आप चाहते हैं वह है नई तिथि () fn का मजाक करना।

आइडिया को ग्लोबल डेट को टेम्पर्ड वैरिएबल में स्टोर करना है, ग्लोबल डे को मॉक करना है और उसके बाद यूज रिस्पाइन टेम्प को ग्लोबल डेट पर पहुंचाना है।

export const stubbifyDate = (mockedDate: Date) => {
    /**
     * Set Date to a new Variable
     */
    const MockedRealDate = global.Date;

    /**
     *  Mock Real date with the date passed from the test
     */
    (global.Date as any) = class extends MockedRealDate {
        constructor() {
            super()
            return new MockedRealDate(mockedDate)
        }
    }

    /**
     * Reset global.Date to original Date (MockedRealDate) after every test
     */
    afterEach(() => {
        global.Date = MockedRealDate
    })
}

Usage in your test would be like

import { stubbyifyDate } from './AboveMethodImplementedFile'

describe('<YourComponent />', () => {
    it('renders and matches snapshot', () => {
        const date = new Date('2019-02-18')
        stubbifyDate(date)

        const component = renderer.create(
            <YourComponent data={}/>
        );
        const tree = component.toJSON();
        expect(tree).toMatchSnapshot();
    });
});



अपना उत्तर भी बताइए। केवल कोड डालना अच्छा तरीका नहीं है
Intsab हैदर

1
सलाह के लिये धन्यवाद। टिप्पणियों के साथ अपडेट किया गया।
प्रणव एस बालूगारी

0

मैं सिर्फ यहाँ पर झंकार करना चाहता था क्योंकि कोई जवाब नहीं था कि आप Dateकिसी विशिष्ट सुइट में वस्तु का मजाक बनाना चाहते हैं ।

आप इसे प्रत्येक सुइट, जेस्ट डॉक्स के लिए सेटअप और टियरडाउन विधियों का उपयोग करके मॉक कर सकते हैं

/**
 * Mocking Date for this test suite
 */
const globalDate = Date;

beforeAll(() => {
  // Mocked Date: 2020-01-08
  Date.now = jest.fn(() => new Date(Date.UTC(2020, 0, 8)).valueOf());
});

afterAll(() => {
  global.Date = globalDate;
});

उम्मीद है की यह मदद करेगा!


0

आप डेट-फेकर का उपयोग कर सकते हैं । चलिए आप वर्तमान तिथि को अपेक्षाकृत बदलते हैं:

import { dateFaker } from 'date-faker';
// or require if you wish: var { dateFaker } = require('date-faker');

// make current date to be tomorrow
dateFaker.add(1, 'day'); // 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond'.

// change using many units
dateFaker.add({ year: 1, month: -2, day: 3 });

// set specific date, type: Date or string
dateFaker.set('2019/01/24');

// reset
dateFaker.reset();

0

जेस्ट 26 के अनुसार इसे किसी भी 3 पार्टी मॉड्यूल को स्थापित करने की आवश्यकता के बिना "आधुनिक" नकली टाइमर का उपयोग करके प्राप्त किया जा सकता है: https://jestjs.io/blog/2020/05/05/jest-26#new-fake-timers

jest
  .useFakeTimers('modern')
  .setSystemTime(new Date('2020-01-01').getTime());
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.