【问题标题】:Handling Apollo-wrapped descendants in unit tests that mount the React component在挂载 React 组件的单元测试中处理 Apollo 包装的后代
【发布时间】:2018-02-22 14:46:30
【问题描述】:

在过去的几个月里,我一直在使用 React 中的 ApolloJS(通过 react-apollo)并学习了许多与单元测试 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 包装的组件?

【问题讨论】:

    标签: reactjs enzyme apollo react-apollo


    【解决方案1】:

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

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

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

    import React from 'react'
    import { mount } from 'enzyme'
    
    // This is an Apollo client I configured in a separate module
    // with a mocked network interface. I won't go into details on
    // that here, but am happy to provide more details if someone asks
    import mockedClient from 'test/mocked_client'
    
    // 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(
          <Assignments assignments={assignments} />,
          {
            context: { client: mockedClient },
            childContextTypes: {
              client: React.PropTypes.object.isRequired
            }
          }
        )
    
        // This now passes!
        expect(wrapper.state('assignments')).to.eql([...])
      })
    })
    

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

    【讨论】:

      猜你喜欢
      • 2020-09-09
      • 1970-01-01
      • 2017-11-19
      • 2023-03-26
      • 1970-01-01
      • 2023-03-31
      • 2015-12-01
      • 1970-01-01
      • 2015-04-27
      相关资源
      最近更新 更多