我试图模拟回调函数(cb),并想检查是否调用1次。
and I've try:
jest.useFakeTimers()
const cb = (t: number) => `message-${t}`
const spy = jest.fn(cb)
// This one also fails.
// jest.spyOn(React, 'useRef').mockReturnValue({ current: cb });
const { result } = renderHook(() => useTimer(3, cb))
await waitFor(() => expect(result.current[0]).toBe(3))
await waitFor(() => expect(result.current[1]).toBe('message-3'))
await waitFor(() => expect(spy).toBeCalledTimes(1)) // received 0
const useTimer = (
startTimeSec: number,
cb: (currentSeconds: number) => string = (c) => '',
): [number, string] => {
const [timer, setTimer] = useState(startTimeSec)
const [intervalTime, setIntervalTime] = useState<null | number>(null)
const [message, setMessage] = useState<string>('')
const callback = React.useRef(cb)
useEffect(() => {
if (startTimeSec) {
setTimer(startTimeSec)
setMessage(callback.current(timer))
}
}, [startTimeSec])
//...
return [timer, message]
}
任何想法?
应该将模拟的回调函数spy
传递给useTimers
而不是cb
。
此外,让我们回顾useRef()
的概念:
useRef返回一个可变ref对象,其
.current
属性初始化为传递的参数(initialValue)。
这意味着你模拟的cb
函数将是.current
属性的值。
。
userTimer.ts
:
import React, { useEffect, useState } from 'react';
const useTimer = (startTimeSec: number, cb: (currentSeconds: number) => string = (c) => ''): [number, string] => {
const [timer, setTimer] = useState(startTimeSec);
const [intervalTime, setIntervalTime] = useState<null | number>(null);
const [message, setMessage] = useState<string>('');
const callback = React.useRef(cb);
useEffect(() => {
if (startTimeSec) {
setTimer(startTimeSec);
setMessage(callback.current(timer));
}
}, [startTimeSec]);
return [timer, message];
};
export { useTimer };
useTimer.test.ts
:
import { waitFor } from '@testing-library/react';
import { renderHook } from '@testing-library/react-hooks';
import { useTimer } from './useTimer';
describe('useTimer', () => {
it('should pass', async () => {
const cb = (t: number) => `message-${t}`;
const spy = jest.fn(cb);
const { result } = renderHook(() => useTimer(3, spy));
await waitFor(() => expect(result.current[0]).toBe(3));
await waitFor(() => expect(result.current[1]).toBe('message-3'));
await waitFor(() => expect(spy).toBeCalledTimes(1));
});
});
单元测试结果:
PASS examples/66452119/useTimer.test.ts
useTimer
✓ should pass (20 ms)
-------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------|---------|----------|---------|---------|-------------------
All files | 92.31 | 33.33 | 66.67 | 100 |
useTimer.ts | 92.31 | 33.33 | 66.67 | 100 | 3-10
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.931 s