如何测试react-to-print的usePrint钩子及修复Jest测试失败问题?
解决usePrint自定义钩子的Jest测试问题
我基于react-to-print实现了组件打印功能,并编写了usePrint自定义钩子:
import { useRef } from "react" import { useReactToPrint } from "react-to-print" export const usePrint = <T extends HTMLElement>() => { const componentRef = useRef<T>(null) const print = useReactToPrint({ content: () => componentRef.current, pageStyle: "padding-inline: 2px", fonts: [ { family: "Inter", source: "https://fonts.googleapis.com/css2?family=Inter&display=swap", }, ], }) return { print, componentRef } }
需要用Jest和Testing Library验证两个核心要点:
useReactToPrint被正确调用(传入预期的配置参数)- 调用
print方法时能触发打印逻辑(对应打开PDF预览的行为)
我原本的测试代码执行失败,核心问题是测试逻辑错误,以下是修正后的完整测试方案:
修正后的测试代码
import { expect, jest } from "@jest/globals" import { act, renderHook } from "@testing-library/react" import { useReactToPrint } from "react-to-print" import { usePrint } from "./usePrint" // 模拟react-to-print的useReactToPrint钩子,让它返回一个模拟函数 jest.mock("react-to-print", () => ({ useReactToPrint: jest.fn(() => jest.fn()), })) test("初始化时componentRef的current值为null", () => { const { result } = renderHook(() => usePrint<HTMLDivElement>()) expect(result.current.componentRef.current).toBeNull() }) test("useReactToPrint被正确调用,且调用print能触发打印逻辑", () => { const { result } = renderHook(() => usePrint<HTMLDivElement>()) // 验证useReactToPrint在钩子初始化时就被调用 expect(useReactToPrint).toHaveBeenCalledTimes(1) // 验证useReactToPrint传入的配置参数符合预期 const useReactToPrintArgs = useReactToPrint.mock.calls[0][0] expect(useReactToPrintArgs.pageStyle).toBe("padding-inline: 2px") expect(useReactToPrintArgs.fonts).toEqual([ { family: "Inter", source: "https://fonts.googleapis.com/css2?family=Inter&display=swap", }, ]) // 验证content函数返回的是componentRef.current const mockRef = { current: document.createElement("div") } // 临时替换componentRef.current result.current.componentRef.current = mockRef.current expect(useReactToPrintArgs.content()).toBe(mockRef.current) // 验证调用print方法时,触发useReactToPrint返回的模拟函数 const mockPrintFn = useReactToPrint.mock.results[0].value act(() => { result.current.print() }) expect(mockPrintFn).toHaveBeenCalledTimes(1) })
关键修正点说明
- 测试时机错误修正:
useReactToPrint是在usePrint钩子初始化阶段就执行的,不是调用print方法时才执行。所以要在renderHook之后直接断言useReactToPrint被调用,而不是调用print之后。 - 模拟函数返回值处理:让
useReactToPrint返回一个模拟函数,这样print变量就是这个模拟函数,调用print后可以断言该模拟函数被执行,以此验证打印逻辑被触发。 - 参数完整性验证:不仅要验证
useReactToPrint被调用,还要验证传入的配置参数(如pageStyle、fonts、content函数)是否符合预期,确保钩子的配置正确。
内容的提问来源于stack exchange,提问作者Ala Eddine Menai
相关产品推荐
相关产品推荐

