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

React Native项目中如何在Jest测试用例中覆盖render内的函数?

你当前测试覆盖率不足的核心原因是:仅对App组件做了基础渲染校验,没有处理componentDidMount的异步逻辑,也未覆盖render内的多条件分支,更没有触发传递给子组件的各类回调方法,所以这部分代码未被覆盖率统计命中。

修复步骤

1. 先Mock外部依赖避免干扰

在测试文件开头添加依赖Mock逻辑,隔离子组件和第三方服务的影响,仅聚焦App组件本身的逻辑测试:

// Mock服务层方法
jest.mock('./services/services', () => ({
  getData: jest.fn(),
  hasPermission: jest.fn()
}))
// Mock所有子组件
jest.mock('../app/components/container/DashboardContainer', () => 'DashboardContainer')
jest.mock('../app/components/container/MenuContainer', () => 'MenuContainer')
jest.mock('../app/components/ui/digitalFooter', () => 'DigitalFooter')
jest.mock('../app/components/container/OffersContainer', () => 'OffersContainer')
jest.mock('../app/components/container/DigitalSearchContainer', () => 'DigitalSearchContainer')
jest.mock('../app/components/container/BMobileDashboardContainer', () => 'BMobileDashboardContainer')
// 异步队列清空工具
const flushPromises = () => new Promise(setImmediate)

2. 覆盖render内opco判断分支

通过MockgetData的返回值,覆盖不同opco下首页组件的渲染逻辑:

test('opco为opco1_rose时渲染BMobileDashboardContainer', async () => {
  require('./services/services').getData.mockImplementation(key => {
    if(key === 'opco') return Promise.resolve('opco1_rose')
    if(key === 'applicationTheme') return Promise.resolve('default')
    if(key === 'applicationMode') return Promise.resolve('light')
    return Promise.resolve('')
  })
  require('./services/services').hasPermission.mockResolvedValue(false)
  const component = renderer.create(
    <ApolloProvider client={client}>
      <MockedProvider addTypename={false}>
        <App navigation={{}} />
      </MockedProvider>
    </ApolloProvider>
  )
  await flushPromises()
  component.update()
  expect(component.root.findByType('BMobileDashboardContainer')).toBeTruthy()
})

按照同样逻辑再补充2条用例,分别把opco设置为mauritius_telecom和default,即可覆盖另外两个首页渲染分支。

3. 覆盖selectedTab切换分支

直接修改组件实例state切换选中标签,覆盖搜索、优惠、菜单页的渲染逻辑:

test('selectedTab为search时渲染DigitalSearchContainer', async () => {
  require('./services/services').getData.mockResolvedValue('default')
  require('./services/services').hasPermission.mockResolvedValue(false)
  const component = renderer.create(
    <ApolloProvider client={client}>
      <MockedProvider addTypename={false}>
        <App navigation={{}} />
      </MockedProvider>
    </ApolloProvider>
  )
  await flushPromises()
  // 切换标签到搜索页
  component.getInstance().setState({ selectedTab: 'search' })
  component.update()
  expect(component.root.findByType('DigitalSearchContainer')).toBeTruthy()
})

按照同样逻辑补充selectedTab为offers、menu的测试用例,即可覆盖剩余标签分支。

4. 覆盖所有未调用的实例方法

触发子组件绑定的回调函数,覆盖方法内部逻辑:

test('所有回调方法逻辑正常', async () => {
  require('./services/services').getData.mockResolvedValue('default')
  require('./services/services').hasPermission.mockResolvedValue(false)
  const component = renderer.create(
    <ApolloProvider client={client}>
      <MockedProvider addTypename={false}>
        <App navigation={{}} />
      </MockedProvider>
    </ApolloProvider>
  )
  await flushPromises()
  component.update()
  const instance = component.getInstance()
  
  // 测试底部标签切换方法
  instance.selectFooterTab('menu')
  expect(instance.state.selectedTab).toBe('menu')
  // 测试搜索页显隐方法
  instance.showSearchScreen(true)
  expect(instance.state.showSearchScreen).toBe(true)
  // 测试底部颜色更新方法
  require('./services/services').getData.mockClear()
  await instance.updateFooterColor()
  expect(require('./services/services').getData).toHaveBeenCalledTimes(2)
  // 触发子组件绑定的回调
  const footer = component.root.findByType('DigitalFooter')
  footer.props.selectFooterTab('offers')
  expect(instance.state.selectedTab).toBe('offers')
})

5. 覆盖主题不存在的兜底分支

Mock不存在的主题值,覆盖signatureHeadingColor的空值兜底逻辑:

test('主题不存在时签名色值返回null', async () => {
  require('./services/services').getData.mockImplementation(key => {
    if(key === 'applicationTheme') return Promise.resolve('unknownTheme')
    return Promise.resolve('default')
  })
  require('./services/services').hasPermission.mockResolvedValue(false)
  const component = renderer.create(
    <ApolloProvider client={client}>
      <MockedProvider addTypename={false}>
        <App navigation={{}} />
      </MockedProvider>
    </ApolloProvider>
  )
  await flushPromises()
  component.update()
  const footer = component.root.findByType('DigitalFooter')
  expect(footer.props.signatureHeadingColor).toBeNull()
})

以上用例全部补充完成后,你截图中所有未覆盖的代码都会被命中,测试覆盖率可以达到要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 11:24:07