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

RTL测试按钮onClick属性失败,请求排查解决

React Testing Library测试Button组件onClick失败问题

我在用React Testing Library测试Button组件时,始终无法通过onClick属性的测试。已模拟onClick函数,却收到以下错误:

expect(jest.fn()).toHaveBeenCalledTimes(expected)

Expected number of calls: 1
Received number of calls: 0

测试代码

import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'

import Button from "../Button/Button"

const handleClick = jest.fn();

describe('Button', () => {
    beforeEach(() => {

        render(
            <Button
                onClick={handleClick}
            >
                buttonText
            </Button>
        )
    })

    it('should render button text', () => {
        const buttonText = "buttonText"
        expect(screen.getByText(buttonText)).toBeInTheDocument()
    })

    it('calls onClick prop when clicked', () => {
        const handleClick = jest.fn();
        const buttonText = "buttonText"
        fireEvent.click(screen.getByText(buttonText))
        expect(handleClick).toHaveBeenCalledTimes(1)
    })
})

Button组件代码

import React from "react";

import { PrimaryButton } from "./Button.styles";

const Button = ({ onClick, children }) => (
    <PrimaryButton
        type="button"
        onClick={onClick}
    >
        {children}
    </PrimaryButton>
);

export default Button;

解决方案

问题根源是测试用例calls onClick prop when clicked内部重新声明了handleClick变量,覆盖了外部定义的模拟函数。实际绑定到Button组件上的是外部的handleClick,但你断言的是测试用例内部新创建的、从未被调用的函数,所以会出现调用次数为0的错误。

修改后的测试代码如下:

import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'

import Button from "../Button/Button"

describe('Button', () => {
    let handleClick;
    
    beforeEach(() => {
        // 每个测试用例前重新初始化模拟函数,避免用例间互相干扰
        handleClick = jest.fn();
        render(
            <Button
                onClick={handleClick}
            >
                buttonText
            </Button>
        )
    })

    it('should render button text', () => {
        const buttonText = "buttonText"
        expect(screen.getByText(buttonText)).toBeInTheDocument()
    })

    it('calls onClick prop when clicked', () => {
        const buttonText = "buttonText"
        fireEvent.click(screen.getByText(buttonText))
        expect(handleClick).toHaveBeenCalledTimes(1)
    })
})

说明

  1. 将handleClick的声明移到describe块内部,在beforeEach中每次创建新的jest模拟函数,保证每个测试用例的独立性,避免测试用例之间的状态污染。
  2. 删除测试用例内部的const handleClick = jest.fn();,直接使用beforeEach中初始化的模拟函数,确保断言的就是绑定到Button组件上的那个函数。

内容的提问来源于stack exchange,提问作者njouro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 22:50:31