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

Jest如何Mock Lerna多包仓库中子包内部使用的useData Hook

问题根因

你当前的Mock写法不生效的核心原因是:@project/shared-component包内部的SharedComponent调用useData时,使用的是包内部相对路径导入,而非包对外暴露的入口导出值。你Mock的是NPM包对外的入口导出,包内部的直接调用不受影响。

可行解决方案

方案1:修改子包内部导入规则(改造成本最低)

将@project/shared-component包内所有调用useData的地方,从相对路径导入改为从包入口导入:

// 改造前(SharedComponent内部导入)
import useData from './hooks/useData'
// 改造后
import { useData } from '@project/shared-component'

改造完成后,SharedComponent内部调用的就是包对外暴露的useData,你原来写的Mock代码即可正常生效。

注意:该方案需要确保你的打包工具(Rollup/TSUP/Vite等)支持处理包内部自引用,当前主流Monorepo场景下的打包工具默认都兼容该写法,不会产生循环依赖问题。

方案2:配置Jest模块映射直接Mock源码

如果不想修改@project/shared-component的业务代码,可以在@project/consumer的Jest配置中添加模块映射,让Jest直接解析子包的源码而非node_modules中的构建产物:

  1. 先修改@project/consumer的jest.config.js配置:
module.exports = {
  moduleNameMapper: {
    // 路径根据你的实际项目目录调整,这里假设两个子包都在packages目录下
    '^@project/shared-component(.*)$': '<rootDir>/../shared-component/src$1',
  }
}
  1. 测试用例中直接MockuseData对应的源码文件:
// 路径对应useData在shared-component包中的实际源码路径
jest.mock('@project/shared-component/hooks/useData', () => ({
  useData: jest.fn(), // 根据实际导出格式调整,默认导出则写default: jest.fn()
}))

方案3:增加依赖注入入口(无侵入无兼容问题)

在@project/shared-component的SharedComponent中增加可选的useData注入参数,默认使用内部实现:

// @project/shared-component 中SharedComponent的实现
import useData from './hooks/useData'

const SharedComponent = (props) => {
  // 优先使用传入的useData,没有则用内部实现
  const { useData: customUseData = useData } = props
  const data = customUseData()
  // 原有组件逻辑
}

测试用例中直接传入Mock后的useData即可:

import { SharedComponent } from '@project/shared-component'

const mockUseData = jest.fn().mockReturnValue({ test: 'mock数据' })

test('测试ConsumerComponent', () => {
  render(<ConsumerComponent useData={mockUseData} />)
  // 测试逻辑
})

该方案不需要修改Jest配置,也不需要调整模块导入规则,不会产生任何打包或解析兼容问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 12:15:05