如何在Jest中测试包含window.print()的React函数组件?
我来帮你梳理下如何用Jest结合React Testing Library测试这个SixLabelReport组件,核心要覆盖模态框激活时触发打印、打印后自动关闭模态框这两个关键逻辑,话不多说直接上步骤和代码:
1. 准备测试依赖
首先确保你已经安装了常规的React测试套件:@testing-library/react、@testing-library/jest-dom以及Jest本身。另外,因为测试环境没有真实的浏览器打印功能,我们需要提前模拟window.print方法。
2. 核心测试用例设计
用例1:模态框激活时触发打印并关闭模态框
这个是组件的核心逻辑,我们需要验证当modalIsVisible为true时,window.print被调用,且setModalIsVisible会被传入false来关闭模态框。
import { render, waitFor } from '@testing-library/react'; import SixLabelReport from './SixLabelReport'; import type { LabelProps } from './your-types-path'; // 替换成你的类型文件路径 describe('SixLabelReport Component', () => { // 构造符合LabelProps的测试数据,根据实际类型调整 const mockLabelData: LabelProps = { deliveryData: { id: 'test-delivery', trackingNo: '12345' }, recipientData: { name: 'Test Recipient', address: 'Test Address' }, senderData: { name: 'Test Sender', address: 'Test Sender Address' } }; const mockLabels = [mockLabelData]; // 每次测试前重置window.print的模拟 beforeEach(() => { jest.spyOn(window, 'print').mockImplementation(() => {}); }); // 测试后恢复原方法,避免影响其他测试 afterEach(() => { jest.restoreAllMocks(); }); it('triggers window.print and closes modal when modal is visible', async () => { const mockSetModalIsVisible = jest.fn(); // 渲染组件,传入激活状态的模态框参数 render( <SixLabelReport labels={mockLabels} modalIsVisible={true} setModalIsVisible={mockSetModalIsVisible} /> ); // 断言print方法被调用一次 expect(window.print).toHaveBeenCalledTimes(1); // 等待useEffect异步执行完成,断言模态框被关闭 await waitFor(() => { expect(mockSetModalIsVisible).toHaveBeenCalledWith(false); }); });
用例2:模态框隐藏时不触发任何打印逻辑
验证当modalIsVisible为false时,组件不会调用window.print,也不会触发模态框状态更新:
it('does not trigger print or modal close when modal is hidden', () => { const mockSetModalIsVisible = jest.fn(); render( <SixLabelReport labels={mockLabels} modalIsVisible={false} setModalIsVisible={mockSetModalIsVisible} /> ); // 确认print没被调用 expect(window.print).not.toHaveBeenCalled(); // 确认模态框状态更新函数没被触发 expect(mockSetModalIsVisible).not.toHaveBeenCalled(); });
用例3:渲染正确数量的Label子组件
验证组件能根据传入的labels数组,渲染对应数量的Label组件:
it('renders correct number of Label components', () => { // 构造2条测试数据 const testLabels = [mockLabelData, mockLabelData]; const { getAllByTestId } = render( <SixLabelReport labels={testLabels} modalIsVisible={false} setModalIsVisible={jest.fn()} /> ); // 通过组件上的data-testid获取所有Label实例,断言数量匹配 expect(getAllByTestId('six-label-report-label')).toHaveLength(testLabels.length); }); });
3. 额外注意事项
- 关于
waitFor:因为useEffect是在组件挂载后异步执行的,所以必须用waitFor包裹状态更新的断言,确保逻辑完全执行完毕后再验证。 - 样式组件的处理:如果
S.Modal和S.Container是styled-components这类样式组件,测试时不需要额外处理,React Testing Library会正常渲染它们,我们只需要关注组件的行为逻辑即可。 - 测试数据准确性:一定要保证
mockLabels的结构完全符合LabelProps的类型定义,避免出现类型错误影响测试结果。
内容的提问来源于stack exchange,提问作者Saulo Castillos
相关产品推荐
相关产品推荐

