2015-04-18 2 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:

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 могут быть использованы в 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(); 
43

Поскольку momentjs использует Date внутри, вы можете просто переписать функцию Date.now всегда возвращает один и тот же момент.

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

Вот немного симпатичнее метод установления фактической даты, которые будут возвращены: 'Date.now = jest.fn (() => новая дата (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; 

 Смежные вопросы

  • Нет связанных вопросов^_^