You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试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)
})

关键修正点说明

  1. 测试时机错误修正:useReactToPrint是在usePrint钩子初始化阶段就执行的,不是调用print方法时才执行。所以要在renderHook之后直接断言useReactToPrint被调用,而不是调用print之后。
  2. 模拟函数返回值处理:让useReactToPrint返回一个模拟函数,这样print变量就是这个模拟函数,调用print后可以断言该模拟函数被执行,以此验证打印逻辑被触发。
  3. 参数完整性验证:不仅要验证useReactToPrint被调用,还要验证传入的配置参数(如pageStyle、fonts、content函数)是否符合预期,确保钩子的配置正确。

内容的提问来源于stack exchange,提问作者Ala Eddine Menai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:55:33