引入
我们自己先写一个定时器,在这里,这个测试是一定会通过的,因为他一旦传入callback,就算是完成了,而不是在意你的运行结果了,而且你的定时器还有几秒呢
export const timer = (fn) => {
setTimeout(() => {
fn()
}, 3000)
}
//test
import {timer} from "./timer"
it("测试timer", () => {
timer(() => {
expect(1).toBe(1)
})
})
done
所以,我们要想等他测试完,那么就是用done()函数,我之前介绍过的,这样测试就不通过了
import {timer} from "./timer"
// test 不通过
it("测试timer", (done) => {
timer(()=>{
expect(2).toBe(1)
done();
})
})
useFakeTimers
但是我们不能真的等3000毫秒,如果是1年呢?所以,我们Mock一个定时器
这里mock完一个定时器,一定要搭配runalltimers使用,不然也是报错的,他的意思,就是让程序巡行完所有的timers
// mock一个定时器
jest.useFakeTimers()
// 测试mock的定时器 通过
it("测试timer", () => {
// mock一个函数
const fn = jest.fn()
// timer传递函数
timer(fn)
// 运行所有的timer
jest.runAllTimers()
// 测试fn的执行次数
expect(fn).toHaveBeenCalledTimes(1)
})
那我如果有两个timers呢? 这里就会通过,因为我把toHaveBeenCalledTimes改为了2,意思是fn函数执行了2次
export const timer = (fn) => {
setTimeout(() => {
fn()
setTimeout(() => {
fn()
}, 5000)
}, 3000)
}
// 测试两个timer
it("测试timer", () => {
// mock一个函数
const fn = jest.fn()
// timer传递函数
timer(fn)
// 运行所有的timer
jest.runAllTimers()
// 测试fn的执行次数
expect(fn).toHaveBeenCalledTimes(2)
})
runOnlyPendingTimers
那如果,我不想测试第二个,就想测试该用例里的第一个定时器呢?
runOnlyPendingTimers 就是告诉程序,仅运行任务队列里的定时器,也就只有第一个,第二个还没添加进去呢
// 测试两个,执行一个
it("测试timer", () => {
// mock一个函数
const fn = jest.fn()
// timer传递函数
timer(fn)
// 运行所有的timer
jest.runOnlyPendingTimers()
// 测试fn的执行次数
expect(fn).toHaveBeenCalledTimes(1)
})
advanceTimersByTime
最后,如果,我想把所有的测试提前3秒呢?会执行几次fn?
这里我们写了两个定时器,时间分别为3秒和5秒,也就是说,我们执行了3秒会执行第一个定时器,再过5秒才会执行第二个定时器,但是我把时间提前3秒,那么fn会被执行一次,但是5秒
的没有执行
export const timer = (fn) => {
setTimeout(() => {
fn()
setTimeout(() => {
fn()
}, 5000)
}, 3000)
}
// 测试加速 通过
it("测试timer", () => {
// mock一个函数
const fn = jest.fn()
// timer传递函数
timer(fn)
// 运行所有的timer
jest.advanceTimersByTime(3000)
// 测试fn的执行次数
expect(fn).toHaveBeenCalledTimes(1)
})
有人说,不对,你试试2秒的定时器
export const timer = (fn) => {
setTimeout(() => {
fn()
setTimeout(() => {
fn()
}, 5000)
}, 3000)
setTimeout(() => {
fn()
}, 2000)
}
这个fn才会是两次,提前了3秒,2秒的已经执行了,3秒的也执行,所以是两次
// 测试加速 通过
it("测试timer", () => {
// mock一个函数
const fn = jest.fn()
// timer传递函数
timer(fn)
// 运行所有的timer
jest.advanceTimersByTime(3000)
// 测试fn的执行次数
expect(fn).toHaveBeenCalledTimes(2)
})
注意,这样写是一次
export const timer = (fn) => {
setTimeout(() => {
fn()
setTimeout(() => {
fn()
}, 5000)
setTimeout(() => {
fn()
}, 2000)
}, 3000)
}