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

ReactJS/JestJS/Enzyme:如何测试compose中graphql的options函数?

如何测试React-Apollo中graphql高阶组件的options函数

嘿,我懂你遇到的问题了!你现在测试的是未被graphql高阶组件包装的原始<Example>组件,那options函数根本没机会执行,覆盖率当然不会统计到它。下面给你两种靠谱的解决办法,按需选就行:

方法一:直接测试提取出来的options纯函数

这是最简单高效的方式,因为options本质就是个接收props返回配置的纯函数,完全可以单独拎出来测试,不用折腾高阶组件的环境。

首先修改你的Example.js,把options函数单独导出:

import React, { Component } from 'react'
import { graphql, compose } from 'react-apollo'
import { getPostsQuery } from './graphql/query'

// 单独导出options函数,方便测试
export const getPostsOptions = (props) => ({
  variables: { articleId: props.articleId }
})

export class Example extends Component {
  render () {
    const { data } = this.props
    const { getPosts, loading } = data
    return (
      <div id="article">
        { getPosts.map(post => {
          return (<div>{post.content}</div>)
        }) }
      </div>
    )
  }
}

export default compose(
  graphql(
    getPostsQuery,
    { options: getPostsOptions } // 这里用导出的函数
  )
)(Example)

然后在测试文件中直接测试这个函数:

import { getPostsOptions } from './components/Example'

describe('getPostsOptions', () => {
  it('should generate correct variables from props', () => {
    const testProps = { articleId: 'test-123' }
    const result = getPostsOptions(testProps)
    
    expect(result.variables).toEqual({ articleId: 'test-123' })
  })
})

这样一来,那行options: (props) => ({...})的代码就被完全覆盖了,而且测试逻辑简单直接,后期维护也方便。

方法二:测试完整的包装后组件(端到端验证)

如果你想验证整个组件流程(包括graphql高阶组件如何使用options发起请求),那就需要测试默认导出的那个被包装后的组件,同时模拟Apollo的运行环境。

首先安装必要的依赖(如果还没装):

npm install @apollo/client enzyme-adapter-react-16 --save-dev

然后编写测试代码:

import React from 'react'
import { mount } from 'enzyme'
import { ApolloProvider, ApolloClient, InMemoryCache } from '@apollo/client'
import Example from './components/Example' // 导入默认导出的包装后组件
import { getPostsQuery } from './graphql/query'

// 创建模拟的Apollo Client
const mockClient = new ApolloClient({
  cache: new InMemoryCache(),
  // 这里可以添加mock链路来模拟请求返回,不过我们主要验证options,所以基础配置就行
})

describe('<Example />', () => {
  it('should execute options function with given props', () => {
    // 监听client的query方法,验证请求参数
    const querySpy = jest.spyOn(mockClient, 'query')
    
    // 用mount渲染组件(shallow不会渲染高阶组件内部逻辑)
    mount(
      <ApolloProvider client={mockClient}>
        <Example articleId="test-456" /> {/* 传递触发options的props */}
      </ApolloProvider>
    )
    
    // 验证query调用时使用了options生成的正确变量
    expect(querySpy).toHaveBeenCalledWith(expect.objectContaining({
      query: getPostsQuery,
      variables: { articleId: 'test-456' }
    }))
  })

  it('should render #article element correctly', () => {
    const wrapper = mount(
      <ApolloProvider client={mockClient}>
        <Example 
          articleId="test-789" 
          data={{ getPosts: [{ content: 'test post' }], loading: false }} 
        />
      </ApolloProvider>
    )
    
    expect(wrapper.find('#article')).toHaveLength(1)
    expect(wrapper.find('#article div').text()).toBe('test post')
  })
})

这种方式能验证整个组件的工作流程,确保options函数确实在组件接收props时被正确调用,生成了预期的请求变量。

两种方法各有优劣:第一种适合单独验证options的逻辑,快速覆盖代码;第二种适合做集成测试,确保组件整体行为符合预期。你可以根据自己的测试需求选择~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:51:36