我如何测试 useState 钩子是否被 jest 和 react 测试库调用?

El *_*men 3 javascript reactjs jestjs react-testing-library

我有这个组件,我想使用 Jest 和 React 测试库进行测试:

export function GenericDivider({ stepsHeader = [], componentsFactory = [] }) {
   const [currentPage, changePage] = useState(0);
   const Component = componentsFactory[currentPage] || (() => <></>);

   return (
    <div className="container page__container">
          ...
                 <a
                   href="#"
                   key={name}
                   onClick={e => {
                     e.preventDefault();
                     if (index < componentsFactory.length) changePage(index);
                   }}
                   className={`nav-link ${currentPage === index && 'active'}`}
                 >
                   {name}
                 </a>
          ...
    </div>
   );
}

export default memo(GenericDivider);
Run Code Online (Sandbox Code Playgroud)

我想测试当我点击时是否调用了 changePage,有没有办法使用 Jest 和 React 测试库来做到这一点?

我是测试新手,我试过这个,但它似乎不起作用

it('Should call changePage when button clicked', () => {
    const changePage = jest.fn();

    const { container } = render(
      <GenericDivider
        stepsHeader={['hamid', 'walid', 'khalid']}
        componentsFactory={[() => <></>, () => <></>, () => <></>]}
      />,
    );

    const button = container.querySelector('a');
    fireEvent.click(button);
    expect(changePage).toHaveBeenCalled();
  });
Run Code Online (Sandbox Code Playgroud)

dan*_*cat 17

简短的回答:不。

测试内部状态变量非常违背react-testing-library背后的理念。该库专注于用户以及用户可以看到的内容。用户没有状态变量的概念。不要进行测试,而是考虑用户会看到的变化,并进行测试。UI如何更新?显示什么不同的标记或样式?从用户的角度考虑如何进行测试,您就会找到答案。

查看react-testing-library 的指导原则以获取更多背景信息。然后浏览此页面,了解哪些查询对您的用例最有意义的指南。

  • @danerismycat:也始终相信这一原则。但最近一个客户拒绝了一个解决方案,因为测试覆盖率不是 80%,并且它指向 useState 行(如果删除,覆盖率确实会很高)。我想知道你会如何处理这样一个要求 ##% 的钩子覆盖率的请求? (2认同)
  • @cfnerd 在这种情况下:渲染父组件,检查子组件是否不在 DOM 中,触发单击,查看子组件现在是否在 DOM 中。如果是的话,你的逻辑就成功了。状态变量被翻转这一事实是一个实现细节;专门的测试不会增加安全性,只会让未来的重构变得更加烦人。 (2认同)
  • @Wordpressor 正确 - 你不应该在测试中调用 setState 。用户无法调用 setState,因此您的测试也不应该调用。是什么导致 setState 被调用并渲染您的组件?触发该用户操作,然后在渲染后测试您的组件。 (2认同)