首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >测试自定义钩子并得到“警告:在测试中对TestHook的更新没有包装在act中

测试自定义钩子并得到“警告:在测试中对TestHook的更新没有包装在act中
EN

Stack Overflow用户
提问于 2019-06-15 16:01:40
回答 1查看 1.6K关注 0票数 3

编辑:我找到了一个解决方案,来自肯特C.多兹的这段视频

只需将jest.advanceTimersByTime调用包装在act函数中即可。

所以这个:

代码语言:javascript
复制
jest.advanceTimersByTime(510);

变成:

代码语言:javascript
复制
act(()=>jest.advanceTimersByTime(510));

我实现了一个简单的自定义钩子,以消除值更新。

以下是代码:

代码语言:javascript
复制
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}

这个钩子的客户端类似于这样(非常简化):

代码语言:javascript
复制
function Search(props) {
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearchTerm = useDebounce(searchTerm, 500);

  // doing something useful with debouncedSearchTerm....
  // ...
  // ...
}

因此,我试图用下面的代码测试钩子:

代码语言:javascript
复制
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');
});

虽然测试通过了,但我收到以下警告:

代码语言:javascript
复制
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实现的,每当值或延迟发生更改时,它都会运行。

我怎样才能摆脱这个警告?我的密码有问题吗?我是不是忘了在测试代码中添加一些内容?

请帮帮我!

EN

回答 1

Stack Overflow用户

发布于 2021-06-03 17:39:05

将该行包装到act

代码语言:javascript
复制
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');
});```
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56611970

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档