如何模拟与useRef绑定的钩子中使用的回调函数?



我试图模拟回调函数(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

最新更新