2017-09-13 53 views
1

過去幾個月,我一直在使用React中的ApolloJS(通過react-apollo),並學習了許多與單元測試相關的技巧和挑戰Apollo-包裹的組件。在安裝React組件的單元測試中處理阿波羅包裹的後代

當測試一個直接用Apollo包裝的組件時,我在導出並測試該組件之前用由graphql返回的HoC進行測試。在測試具有阿波羅包裝組件的組件作爲後代時,我儘可能使用Enzyme的shallow渲染來防止安裝該後代。如果需要通過mount進行全DOM渲染,我使用Apollo測試工具中的MockedProvider,以便後代不會嘗試訪問this.context時發生錯誤。

但是,我還沒有找到一個解決方案,但是,對於下列情況:一個包含Apollo包裹後裔的組件需要使用完全DOM呈現進行測試,但我還需要做出涉及組件實例的斷言(例如狀態,實例方法等)。爲了避免後代問題,我必須將組件包裝在模擬的提供者中,但這意味着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([...]) 
    }) 
}) 

我試圖找到通過酶的方式來訪問一個孩子的組件實例,而不是根,據我可以告訴,不支持。我也一直試圖在這些測試中找到需要MockedProvider的替代品,但還沒有發現任何東西。

有沒有人想出瞭解決這種情況的解決方法,還是有不同的方法,我應該採取處理嵌套阿波羅包裹的組件?

回答

1

我找到了解決我的問題的方法。 Apollo包裝的組件的後裔導致問題的原因是當他們嘗試訪問this.context.client時會引發錯誤。 Apollo的MockedProvider創建了一個Apollo客戶端(或者可選地使用您提供的),並通過上下文將其提供給其子女。

結果酶的mount方法允許您指定組件的context。之前我曾嘗試過使用過,但沒有意識到我還需要將它與childContextTypes結合起來,以便將該上下文傳遞給安裝組件的後代。使用這些酶選項可以避免使用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([...]) 
    }) 
}) 

希望這可以幫助別人誰發現自己處於類似的情況!