typescript - ทำไมพฤติกรรมของ `jest.useFakeTimers` ถึงแตกต่างเมื่อเรียกใช้ภายในกับภายนอก `beforeEach` ใน React Native
ภาพรวม
ฉันพบพฤติกรรมที่แตกต่างกันของ jest.useFakeTimers เมื่อเรียกใช้ภายใน beforeEach เทียบกับเรียกใช้ภายนอก
ตัวอย่างที่สามารถทำซ้ำได้
// Foo.tsx
import * as React from 'react';
import {View} from 'react-native';
const Foo: React.FC = () => {
const [timePassed, setTimePassed] = React.useState<number>(0);
const [flag, setFlag] = React.useState(true);
console.log(`timePassed: ${timePassed}, flag: ${flag}`);
React.useEffect(() => {
if (flag) {
setTimeout(() => {
if (timePassed > 1) {
setFlag(false);
}
setTimePassed(timePassed + 1);
}, 1);
}
}, [flag, timePassed]);
return <View />;
};
export default Foo;
// foo.outside.test.tsx
import * as React from 'react';
import {render} from '@testing-library/react-native';
import Foo from '../Foo';
jest.useFakeTimers();
describe('Test Foo', () => {
test('1', () => {
render(<Foo />);
jest.runAllTimers();
});
test('2', () => {
render(<Foo />);
jest.runAllTimers();
});
});
// foo.inside.test.tsx
import * as React from 'react';
import {render} from '@testing-library/react-native';
import Foo from '../Foo';
describe('Test Foo', () => {
// fake timer usage follows: https://testing-library.com/docs/using-fake-timers/
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.runOnlyPendingTimers();
jest.useRealTimers();
});
test('1', () => {
render(<Foo />);
jest.runAllTimers();
});
test('2', () => {
render(<Foo />);
jest.runAllTimers();
});
});
ผลการทดสอบ
ข้างนอก
npx jest __tests__/foo.outside.test.tsx
console.log
timePassed: 0, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 1, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 2, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 2, flag: false
at log (Foo.tsx:8:11)
console.log
timePassed: 3, flag: false
at log (Foo.tsx:8:11)
console.log
timePassed: 0, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 1, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 2, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 2, flag: false
at log (Foo.tsx:8:11)
console.log
timePassed: 3, flag: false
at log (Foo.tsx:8:11)
PASS __tests__/foo.outside.test.tsx
Test Foo
✓ 1 (58 ms)
✓ 2 (21 ms)
ข้างใน
npx jest __tests__/foo.inside.test.tsx 1 ↵
console.log
timePassed: 0, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 1, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 2, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 2, flag: false
at log (Foo.tsx:8:11)
console.log
timePassed: 3, flag: false
at log (Foo.tsx:8:11)
console.log
timePassed: 0, flag: true
at log (Foo.tsx:8:11)
console.log
timePassed: 1, flag: true
at log (Foo.tsx:8:11)
PASS __tests__/foo.inside.test.tsx
Test Foo
✓ 1 (62 ms)
✓ 2 (14 ms)
การสังเกต
ดูเหมือนว่าในการตั้งค่า ภายนอก jest.runAllTimers จะทำให้ตัวจับเวลาทำงานจนจบในทั้งสองกรณีทดสอบ อย่างไรก็ตาม ในการตั้งค่า ภายใน มีเพียงตัวจับเวลาในกรณีทดสอบแรกที่ทำงานจนจบ; ตัวจับเวลาในกรณีทดสอบที่สองจะสิ้นสุดก่อนเวลา
คำถาม
ทำไมพฤติกรรมของตัวจับเวลาปลอมถึงต่างกันเมื่อเรียกใช้ jest.useFakeTimers ภายในและภายนอก beforeEach? ฉันคาดว่าการตั้งค่าทั้งสองแบบจะรันตัวจับเวลาไปจนจบ ดังนั้นพฤติกรรมปัจจุบันของการตั้งค่า ภายใน จึงเป็นเรื่องน่าประหลาดใจในเชิงลบ
ข้อมูลเครื่องและซอฟต์แวร์
- macOS Big Sur v11.6.5
- รีแอ็กต์: 17.0.2
- react-native: 0.65.1
- เจสต์: 28.1.2
- @testing-library/react-native: 10.1.1
- ไทป์สคริปต์: 4.5.2