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

如何在Jest中保留可用的手动Mock并兼容CRA的resetMocks新默认值?

解决CRA 4.0.0中resetMocks: true导致手动Mock失效的问题

我刚好踩过这个坑!CRA 4.0.0默认开启的resetMocks: true确实会搞砸你在__mocks__里定义的手动Mock,导致Jest抛出mockConstructor(...): Nothing was returned from render的错误。不过别担心,我们可以找到一个两全其美的方案——既保留手动Mock的功能,又能享受resetMocks带来的测试用例间状态隔离优势。

问题根源

resetMocks: true的作用是在每个测试用例执行后,重置所有Jest mock的状态——包括把mock函数的实现重置为空。你的__mocks__/SomeComponent.js里是用jest.fn().mockImplementation(...)来定义Mock组件的,所以每次测试结束后,这个mock的实现会被清空,下一个测试运行时,组件渲染就会返回undefined,自然报错。

完美解决方案:让Mock自动恢复实现

我们只需要修改手动Mock的写法,让它在每次测试前自动恢复自己的实现,同时让resetMocks继续帮我们清理调用次数、参数这些状态。

修改__mocks__/SomeComponent.js

把原来的Mock代码改成这样:

// src/__mocks__/SomeComponent.js
const implementation = () => <p>mocked SomeComponent</p>

// 初始化mock时直接绑定实现
const SomeComponent = jest.fn(implementation)

// 每次测试前,重新绑定实现(应对resetMocks的重置)
beforeEach(() => {
  SomeComponent.mockImplementation(implementation)
})

export default SomeComponent

这样一来,不管resetMocks怎么重置mock的状态,我们都会在测试开始前把实现给补回去,Mock组件就能正常渲染了。

优化测试文件(可选)

另外,你原来测试文件里的beforeEach调用mockClear()其实可以删掉了——因为resetMocks: true已经会自动帮我们重置mock的调用次数、参数等状态,完全覆盖了mockClear()的功能:

// src/App.test.js
import { render, screen } from '@testing-library/react'
import App from './App'
import SomeComponent from './SomeComponent'

jest.mock('./SomeComponent')

// 删掉这部分,resetMocks已经处理了
// beforeEach(() => {
//  SomeComponent.mockClear()
// })

it('should contain mocked component', () => {
  render(<App />)
  screen.getByText(/mocked SomeComponent/i)
})

it('should have correct calledTimes', () => {
  render(<App />)
  screen.getByText(/mocked SomeComponent/i)
  expect(SomeComponent).toHaveBeenCalledTimes(1)
})

备选方案:局部禁用resetMocks(不推荐)

如果你不想修改所有Mock文件,也可以在单个测试文件里禁用resetMocks,但这样会失去测试间的状态隔离,需要手动清理mock状态,所以不如上面的方案优雅:

// 在测试文件顶部添加,仅当前文件禁用resetMocks
jest.config.resetMocks = false;

但这种方式下,你需要手动在beforeEach里调用mockClear()或者mockReset()来清理状态,不然测试用例间会互相影响。

验证效果

修改完之后运行测试,你会发现两个测试都能顺利通过:

  • 第一个测试正确渲染了Mock组件的内容
  • 第二个测试里calledTimes依然是1,说明resetMocks依然在正常工作,清理了上一个测试的调用记录

这样就既保住了你的手动Mock,又没浪费CRA新默认配置带来的测试隔离优势~

内容的提问来源于stack exchange,提问作者ian-s-mcb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 13:27:38