触发fireEvent.click后NavbarContainer组件未更新,Jest测试报错如何解决
问题根因
你写的测试代码中,用于控制组件渲染的menuOpen是普通JavaScript变量,不是React的响应式状态。修改普通变量的值不会触发React的重渲染逻辑,因此哪怕你验证了menuOpen的变量值发生了变化,NavbarContainer组件仍然使用渲染时传入的初始值,不会更新UI,自然找不到你预期的按钮元素。
此外你的测试代码中还有两处不必要的await使用:fireEvent是同步API,queryBy系列查询也是同步API,不需要加await。
修复方案
在测试中封装一个用于托管状态的包装组件,使用React的useState管理menuOpen的状态,保证状态更新后能触发组件重渲染。修复后的测试代码如下:
import { useState } from 'react'; import { render, fireEvent } from '@testing-library/react'; import { BrowserRouter } from 'react-router-dom'; // 省略你自己的组件导入 describe("NavbarContainer", () => { i18n.changeLanguage('cimode'); let component; // 测试用状态托管包装组件 const TestWrapper = () => { const [menuOpen, setMenuOpen] = useState(true); const openMenu = () => { // 用函数式更新保证取到最新的状态值 setMenuOpen(prevState => !prevState); }; return ( <BrowserRouter basename="/"> <NavbarContainer menuOpen={menuOpen} functionality={openMenu} activeLink="" /> </BrowserRouter> ); }; beforeEach(() => { component = render(<TestWrapper />); }); it("点击后显示菜单按钮", () => { const backButton = component.getByText("navbar.back"); fireEvent.click(backButton); const menuButton = component.getByText("navbar.menu"); expect(menuButton).toBeInTheDocument(); }); });
补充说明
如果不想写包装组件,也可以在状态变更后手动调用rerender方法传入新的menuOpen值,但用包装组件的写法更贴近组件实际的使用场景,测试可信度更高。
内容的提问来源于stack exchange,提问作者Chochomona
相关产品推荐
相关产品推荐

