2015-04-18 66 views
27

我正在使用moment.js在我的React組件的幫助文件中完成大部分日期邏輯,但是我一直無法弄清楚如何在Jest a la sinon.useFakeTimers()中模擬日期。如何在Jest中設置模擬日期?

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

    }); 

}); 

現在,這些測試都通過了,因爲我用一下,我的函數使用時刻,但它似乎有點不穩定,我想將日期設置爲測試的固定時間。

關於如何完成這個任何想法?

回答

21

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(); 
43

由於momentjs使用Date內部,你可以只覆蓋Date.now函數總是返回同一時刻。

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

這裏的設置將被返回的實際日期的一點點漂亮方法:'Date.now = jest.fn (()=> new Date(Date.UTC(2017,0,1))。valueOf());' – developering

9

jest.spyOn作品鎖定時間:

let dateNowSpy; 

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

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

偉大的解決方案;沒有依賴性並保持可重置性,因此可以輕鬆應用於單個測試。 –

0

所有僅基於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;