要点:beforeEach mock、afterEach 复原。
方式 1:mock global method
const now = Date.now;
beforeEach(() => {
// tell vitest we use mocked time
global.Date.now = vi.fn(() => 1687233777420);
})
afterEach(() => {
// restoring date after each test run
global.Date.now = now;
})
优点:
- 简单,易读。如果单个方法 mock 可以使用方式 1.
缺点:
- 需要逐个方法 mock,若使用到了 Date.now 之外的方法还得新增 mock 实现。
方式 2:官方 setSystemTime
优点:
- 一次 mock 所有 Date 方法都被 mock
缺点:
- 需要涉及多个 api 和增加很多『仪式』:
useFakeTimers、useRealTimers、setSystemTime
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
const businessHours = [9, 17]
function purchase() {
const currentHour = new Date().getHours()
const [open, close] = businessHours
if (currentHour > open && currentHour < close)
return { message: 'Success' }
return { message: 'Error' }
}
describe('purchasing flow', () => {
beforeEach(() => {
// tell vitest we use mocked time
vi.useFakeTimers()
})
afterEach(() => {
// restoring date after each test run
vi.useRealTimers()
})
it('allows purchases within business hours', () => {
// set hour within business hours
const date = new Date(2000, 1, 1, 13)
vi.setSystemTime(date)
// access Date.now() will result in the date set above
expect(purchase()).toEqual({ message: 'Success' })
})
it('disallows purchases outside of business hours', () => {
// set hour outside business hours
const date = new Date(2000, 1, 1, 19)
vi.setSystemTime(date)
// access Date.now() will result in the date set above
expect(purchase()).toEqual({ message: 'Error' })
})
})