如何在Jest中设置模拟日期?

2022-08-30 00:32:34

我正在使用 moment.js在 React 组件的帮助程序文件中执行大部分日期逻辑,但我无法弄清楚如何在 Jest a la 中模拟日期。sinon.useFakeTimers()

Jest文档只谈论计时器功能,如,等等,但没有帮助设置日期,然后检查我的日期函数是否做了他们应该做的事情。setTimeoutsetInterval

这是我的一些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);
    });
    
  });

});

现在这些测试通过,因为我正在使用时刻,我的函数使用时刻,但它似乎有点不稳定,我想将日期设置为测试的固定时间。

关于如何实现这一目标的任何想法?


答案 1

从Jest 26开始,这可以使用“现代”假计时器来实现,而无需安装任何第三方模块:https://jestjs.io/blog/2020/05/05/jest-26#new-fake-timers

jest
  .useFakeTimers()
  .setSystemTime(new Date('2020-01-01'));

如果希望假计时器在所有测试中处于活动状态,可以在配置中设置:https://jestjs.io/docs/configuration#timers-stringtimers: 'modern'

编辑:截至Jest 27,现代假计时器是默认值,因此您可以将参数删除到。useFakeTimers


答案 2

由于 momentjs 在内部使用,因此您可以只覆盖函数以始终返回相同的时刻。DateDate.now

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

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