✅
VitestでsetTimeoutを含むコードのテストを書く
なにこれ
Vitestでの非同期処理に苦しんでいる人向け。
結論
テストする処理
const someValue = ref(false);
const doSomething = () => {
setTimeout(() => {
someValue.value = true;
}, 500);
};
testコード
describe('test with setTimeout!', () => {
test('doSomething', () => {
vi.useFakeTimers({
shouldAdvanceTime: true,
}); // #1
doSomething();
vi.advanceTimersByTime(500); // #2
expect(someValue.value).toBeTruthy();
vi.useRealTimers(); // #3
});
});
解説
-
vi.useFakeTimers
でtimerをmockする[1]- この際、
shouldAdvanceTime
をtrueに設定する[2]ことで2.
でmockしたtimerの時間を進められるようになる - 参照:
- この際、
-
vi.advanceTimersByTime
でtimerの時間を進める - (後処理)
vi.useRealTimers
でtimerのmockを解除- 参照:
補記
- 「
shouldAdvanceTime
をtrueに設定する」について- この設定の用途が「mockしたtimerを実際の時間に伴って進める」であることを踏まえると、意図した実装ではないようです
- 参照: Component test with setTimeout and vitest fake timers not working · Issue #1198 · testing-library/react-testing-library
- このissueで議論中っぽい: Update to v14 breaks @testing-library/user-event on Vitest · Issue #1197 · testing-library/react-testing-library
まとめ
動くと見せかけて動かないパターン、まれによくある。
それではまた次回。
Discussion