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

React Testing Library测试问题:点击时event.target.href自动拼接域名

问题原因与解决方案

你遇到的问题是因为JSDOM(React Testing Library 依赖的模拟浏览器环境)会自动将 <a> 标签的 href 属性解析为绝对 URL。你测试里 mock 的 target.href 不会生效——fireEvent 触发点击时,事件对象的 target 是真实渲染的 <a> DOM 元素,它的 href 已经被 JSDOM 处理成了基于默认测试域名(https://www.example.com/)的绝对路径,所以实际传入 onLinkClick 的是解析后的完整 URL,而非你 mock 的 foo.com。

两种解决思路

思路一:修改组件,获取原始 href 属性值

如果你的需求是传递 <a> 标签上设置的原始 href 值(而非浏览器解析后的绝对 URL),可以把组件里的 e.target.href 替换为 e.currentTarget.getAttribute('href'):

const MyButton = ({ onLinkClick }) => {
    const handleClick = e => {
        e.preventDefault()
        // getAttribute 会返回标签上设置的原始属性值,不会被解析为绝对 URL
        onLinkClick({ href: e.currentTarget.getAttribute('href'), foo: 'bar', baz: 'quz' })
    }

    return (
        <a href='some-url' onClick={handleClick}>Click me</a>
    )
}

对应的测试可以直接断言原始值:

expect(props.onLinkClick).toHaveBeenCalledWith({
    href: 'some-url',
    foo: 'bar',
    baz: 'quz',
})

思路二:在测试中使用解析后的绝对 URL

如果你确实需要传递浏览器解析后的绝对 URL,测试里的期望值要和 JSDOM 生成的结果一致:

// 计算 JSDOM 会生成的绝对 URL
const expectedHref = new URL('foo.com', 'https://www.example.com/').href;

expect(props.onLinkClick).toHaveBeenCalledWith({
    href: expectedHref, // 对应 "https://www.example.com/foo.com"
    foo: 'bar',
    baz: 'quz',
})

另外,你测试里的 mockEvent 其实没有作用,因为 fireEvent 的事件对象 target 是真实 DOM 元素。如果要修改 <a> 的 href 属性,应该在渲染后直接操作 DOM:

const link = screen.getByRole('link');
// 修改 DOM 元素的 href 属性
link.href = 'foo.com';

fireEvent.click(link);

expect(props.onLinkClick).toHaveBeenCalledWith({
    href: new URL('foo.com', 'https://www.example.com/').href,
    foo: 'bar',
    baz: 'quz',
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:21:15