编辑:我找到了一个解决方案,来自肯特C.多兹的这段视频。
只需将jest.advanceTimersByTime调用包装在act函数中即可。
所以这个:
jest.advanceTimersByTime(510);变成:
act(()=>jest.advanceTimersByTime(510));我实现了一个简单的自定义钩子,以消除值更新。
以下是代码:
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}这个钩子的客户端类似于这样(非常简化):
function Search(props) {
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 500);
// doing something useful with debouncedSearchTerm....
// ...
// ...
}因此,我试图用下面的代码测试钩子:
import { renderHook, act } from 'react-hooks-testing-library';
import useDebounce from '../useDebounce';
jest.useFakeTimers();
it.only('should update value after specified delay', () => {
const { result, rerender } = renderHook(
({ value, delay }) => useDebounce(value, delay),
{ initialProps: { value: '', delay: 500 } }
);
expect(result.current).toBe('');
jest.advanceTimersByTime(510);
expect(result.current).toBe('');
rerender({ value: 'Hello World', delay: 500 });
expect(result.current).toBe('');
jest.advanceTimersByTime(498);
expect(result.current).toBe('');
jest.advanceTimersByTime(3);
expect(result.current).toBe('Hello World');
});虽然测试通过了,但我收到以下警告:
console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:102
Warning: An update to TestHook inside a test was not wrapped in act(...). When testing, code that causes React state updates should be wrapped into act(...): act(() => { /* fire events that update state */ }); /* assert on the output */ This ensures that you're testing the behavior the user would see in the browser. Learn more at..... in TestHook in Suspense我知道,如果我要调用一个函数来更新钩子的内部状态(例如,useCounter钩子的增量()),我必须按照文档的指示,在act函数中这样做。
但是,我实现的useDebounce钩子状态是由一个内部useEffect实现的,每当值或延迟发生更改时,它都会运行。
我怎样才能摆脱这个警告?我的密码有问题吗?我是不是忘了在测试代码中添加一些内容?
请帮帮我!
发布于 2021-06-03 17:39:05
将该行包装到act中
it.only('should update value after specified delay', () => {
const { result, rerender } = renderHook(
({ value, delay }) => useDebounce(value, delay),
{ initialProps: { value: '', delay: 500 } }
);
expect(result.current).toBe('');
jest.advanceTimersByTime(510);
expect(result.current).toBe('');
rerender({ value: 'Hello World', delay: 500 });
expect(result.current).toBe('');
jest.advanceTimersByTime(498);
expect(result.current).toBe('');
// once delay time is passed, component is rerendered, so to capture that
// in unit test, this line should be wrapped in act
act(() => jest.advanceTimersByTime(3));
expect(result.current).toBe('Hello World');
});```https://stackoverflow.com/questions/56611970
复制相似问题