如何使用 Jest 模拟 Date 对象
AWS AI 直播!
我花了太多时间试图正确地模拟 JavaScript 的 Date 对象。我尝试了一些在 Google 上找到的方法……但都失败了。最终,我只能自己摸索出一个解决方案。
我们每次嘲讽,都会偏离现实世界。
因此,我一般不会嘲讽……但有时候,选择确实不多。幸运的是,Date 是个不错的例外!
大家都在同一时区!
为了避免时区相关的问题(例如日期格式问题),您可以在 Jest 配置文件中设置节点时区。这样,无论您的同事或 CI 服务器位于何处,都能确保所有测试都在同一时区执行。
// jest.config.js
process.env.TZ = 'GMT';
module.exports = {
// ...
}
另请参阅:时区完整列表(列TZ 数据库名称)
模拟约会。现在
假设我想测试一个仪表盘组件,它会显示“你好”以及当天的日期。最简单的方法是只测试“你好”这部分(不包含日期),因为日期每天都会变化。但这样就无法测试日期格式化部分。
如果你想的话,你需要模拟Date.now()并设置一个默认值。
// your-test.spec.js
const RealDate = Date.now
beforeAll(() => {
global.Date.now = jest.fn(() => new Date('2019-04-07T10:20:30Z').getTime())
})
afterAll(() => {
global.Date.now = RealDate
})
现在,在同一个文件中,您可以添加类似以下内容:
it('should show a formatted date of today', async () => {
const dashboard = await Mount(<Dashboard />)
expect(dashboard).toHaveText('Hi Max, today is 7 April 2019')
})
💡RealDate存储“真实”的 Date 实例,以便之后可以将其放回原处。
使用 Moment.js 吗?
您可能正在使用非常流行的 moment.js 库。如果是这样,仅仅模拟 moment.jsDate.now可能不够。
一种解决方法是模拟整个 node 模块。
// <root>/__mocks__/moment.js
const moment = jest.requireActual('moment');
Date.now = () => new Date('2019-04-07T10:20:30Z').getTime();
module.exports = moment;
有了这个方案,你就不需要beforeAll()监听afterAll()器了。这个模拟对象对所有测试都有效。
而且,每次moment()调用,返回日期都一样🎉
我建议您做的第一件事就是设置默认时区。
// jest.config.js
process.env.TZ = 'GMT';
module.exports = {
// ...
}
模拟日期对象
// your-test.spec.js
const RealDate = Date;
beforeEach(() => {
global.Date.now = jest.fn(() => new Date('2019-04-22T10:20:30Z').getTime());
});
afterEach(() => {
global.Date = RealDate;
});
使用 Moment?
如果你使用的是流行的 moment.js 库,仅仅进行模拟Date.now可能还不够。查看 moment 的源代码,你会发现
需要用另一种方式来模拟 JavaScript 的 Date 对象。
// <root>/__mocks__/moment.js
const moment = jest.requireActual('moment');
Date.now = () => new Date('2019-04-22T10:20:30Z').getTime();
module.exports = moment;
感谢您抽出时间阅读这篇文章。希望对您有所帮助!如果您喜欢,请点个赞❤️或🦄!也欢迎在下方评论区留言或提问,或者在推特上联系我 @_maxpou :)
原文发表于maxpou.fr。
文章来源:https://dev.to/maxpou/how-to-mock-date-with-jest-3k4b