如何使用Enzyme/Jest测试React中经Props设置状态的组件
问题根因
测试不通过的核心原因是被测组件是标准的受控组件:组件本身不持有isShowing状态,状态值完全由父组件通过props注入,状态更新也完全依赖父组件传入的setShow方法。你在测试中传入的setShow是空函数,点击按钮触发后不会对传入的isShowing值做任何修改,isShowing始终为初始的false,自然不会渲染出h1标签。
测试逻辑
这类受控组件的测试不需要覆盖状态本身的流转逻辑(状态管理是父组件的职责),只需要验证两个核心行为:
- 传入不同props时,组件渲染结果符合预期
- 触发交互动作时,组件会以正确的参数调用传入的状态更新方法
如果需要验证点击后内容显示的完整交互链路,可以在测试侧模拟父组件的行为:要么用mock函数捕获setShow的调用参数后手动更新组件props,要么写一个轻量包装组件,用真实的React状态管理逻辑对接被测组件。
修正后的测试代码
单元测试写法(隔离验证组件逻辑)
import Enzyme, { mount } from 'enzyme'; import EnzymeAdapter from 'enzyme-adapter-react-16'; // 注意替换为你的组件实际路径 import { Component } from './Component'; Enzyme.configure({ adapter: new EnzymeAdapter() }); describe('Component works as expected', () => { test('点击按钮时会传入取反后的状态值调用setShow', () => { const mockSetShow = jest.fn(); const wrapper = mount(<Component isShowing={false} setShow={mockSetShow} />); wrapper.find('button').simulate('click'); // 验证调用setShow时传入的参数是!false也就是true expect(mockSetShow).toHaveBeenCalledWith(true); wrapper.unmount(); }); test('isShowing为true时渲染Showing文案,为false时不渲染', () => { const mockSetShow = jest.fn(); const wrapper = mount(<Component isShowing={false} setShow={mockSetShow} />); // 初始状态下h1不存在 expect(wrapper.find('h1').exists()).toBe(false); // 模拟父组件传入更新后的状态 wrapper.setProps({ isShowing: true }); expect(wrapper.find('h1').text()).toBe("Showing"); wrapper.unmount(); }); });
集成测试写法(模拟真实使用场景)
如果要覆盖完整交互流程,可以写一个简单的包装组件模拟父组件的状态管理,不需要手动更新props:
import React, { useState } from 'react'; import Enzyme, { mount } from 'enzyme'; import EnzymeAdapter from 'enzyme-adapter-react-16'; import { Component } from './Component'; Enzyme.configure({ adapter: new EnzymeAdapter() }); describe('Component full interaction', () => { test('点击按钮可以正常切换内容显隐', () => { // 测试用父组件,持有真实状态 const TestWrapper = () => { const [isShowing, setShow] = useState(false); return <Component isShowing={isShowing} setShow={setShow} />; }; const wrapper = mount(<TestWrapper />); // 初始状态不显示h1 expect(wrapper.find('h1').exists()).toBe(false); // 第一次点击显示内容 wrapper.find('button').simulate('click'); expect(wrapper.find('h1').text()).toBe("Showing"); // 第二次点击隐藏内容 wrapper.find('button').simulate('click'); expect(wrapper.find('h1').exists()).toBe(false); wrapper.unmount(); }); });
注意:如果使用React 17/18版本,需要替换对应版本的enzyme适配器,或者切换为React Testing Library,测试逻辑是一致的。
内容的提问来源于stack exchange,提问作者Pikica
相关产品推荐
相关产品推荐

