在安装React组件的单元测试中处理Apollo包装的后代

时间:2017-09-13 19:10:39

标签: reactjs enzyme apollo react-apollo

在过去的几个月里,我一直在React(通过react-apollo)中使用ApolloJS,并且已经学会了与Apollo包装组件单元测试相关的一些技巧和挑战。

在测试直接用Apollo包装的组件时,我导出并测试组件,然后用graphql返回的HoC进行包装。当测试具有Apollo包裹组件作为后代的组件时,我尽可能使用Enzyme的shallow渲染来防止该后代的安装。如果需要通过mount进行完整的DOM渲染,我使用来自Apollo测试工具的MockedProvider,以便后代不会在尝试访问this.context时抛出错误。

我没有找到解决方案,但是,对于以下情况:需要使用完整DOM渲染测试具有Apollo包装后代的组件,但我还需要进行涉及组件实例的断言(例如状态,实例方法)等)。为了避免后代出现问题,我必须将组件包装在模拟的提供程序中,但这意味着wrapper上的任何断言都在MockedProvider实例上运行,而不是我想要测试的组件。

一个例子:

import { mount } from 'enzyme'
import { MockedProvider } from 'react-apollo/lib/test-utils'

// This component has descendants that are wrapped in Apollo and
// thus need access to `this.context` provided by an Apollo provider
import Assignments from 'app/components/assignments

...

describe('<Assignments />', function() {
  it('sets sorted assignments in initial state', function() {
    const assignments = [...]

    const wrapper = mount(
      <MockedProvider>
        <Assignments assignments={assignments} />
      </MockedProvider>
    )

    // This will fail because the wrapper is of the MockedProvider
    // instance, not the Assignments instance
    expect(wrapper.state('assignments')).to.eql([...])
  })
})

我试图通过Enzyme找到一种方法来访问一个孩子的组件实例,而不是根目录,根据我的判断,我不支持。我也一直试图在这些测试中找到需要MockedProvider的替代品,但还没有找到任何东西。

有没有人为这种情况找到解决方法,或者我应该采用不同的方法来处理嵌套的Apollo包装组件?

1 个答案:

答案 0 :(得分:4)

我找到了解决问题的方法。 Apollo包装的已安装组件的后代导致问题的原因是它们在尝试访问table_cube时会抛出错误。 Apollo的this.context.client创建了一个Apollo客户端(或者可选地使用你提供的客户端),并通过上下文将其提供给子女。

结果Enzyme的MockedProvider方法允许您指定组件的context。我之前尝试过使用它,但没有意识到我还需要将它与childContextTypes结合起来,以便将该上下文传递给已安装组件的后代。使用这些酶选项可以避免使用mount

我将根据原始问题中提供的示例演示解决方案:

MockProvider

希望这有助于发现自己处于类似情况的人!