2015-09-24 123 views
20

我正在嘗試React + Relay + Graphql這幾天。不幸的是,我找不到任何簡單方便的方法來測試由Relay Container包裝的React組件。Relay + React測試策略

基本上,我想實現這些目標一起TDD,

  1. 渲染貨櫃及測試的內容,
  2. 變化的變量和測試內容及其變化。

與React + Flux相比,React + Relay更像黑匣子,或者是聲明性的。

我可以看到人們模擬Relay.createContainer繞過繼電器,只是測試React組件。它使得繼電器部分露出並且沒有辦法通過測試驅動器這部分。 https://github.com/facebook/relay/issues/161

此外,我通讀了Relay的測試用例,以及它渲染模擬容器的繁瑣工作。 https://github.com/facebook/relay/blob/master/src/tools/mocks/RelayTestUtils.js

如果您能分享您的解決方案,我將不勝感激。

謝謝!

+0

反應母語,我認爲這是最好的想法:http://stackoverflow.com/questions/38327428/integration-testing-繼電器容器 - 與 - 開 - 對 - 工作 - graphql-back –

回答

12

我一直試圖測試中繼容器,就像我將在Flux應用程序中的組件一樣。具體來說,我想確保他們爲給定的狀態和道具提供正確的內容,並且他們調用方法在適當的位置更改數據;在Flux中,這是對動作創建者的調用,在Relay中,這是對Relay.Store.updatethis.props.relay.setVariables的調用。

我的第一個嘗試是用renderContainerIntoDocument方法構建一個RelayTestUtil對象。我基於https://github.com/facebook/relay/blob/master/src/tools/mocks/RelayTestUtils.jshttps://github.com/facebook/relay/blob/master/src/legacy/store/mocks/GraphQLStoreQueryResolver.js以及Relay Container測試。這使用了非常小的模擬,非常適合測試容器渲染,但對於測試數據更改完全沒有用處。試圖窺探Relay.Store.updatethis.props.relay.setVariables的電話,或者模擬數據更改,變得比它值得的更麻煩。

我決定添加__mocks__\react-relay.js來完全模擬Relay並使用更簡單的版本RelayTestUtils.renderContainerIntoDocument將Relay屬性注入容器。我對這個解決方案並不完全滿意,但它現在似乎工作。

__mocks__\react-relay.js

var Relay = require.requireActual('react-relay'); 
var React = require('react'); 

module.exports = { 
    QL: Relay.QL, 
    Mutation: Relay.Mutation, 
    Route: Relay.Route, 
    Store: { 
    update: jest.genMockFn() 
    }, 
    createContainer: (component, containerSpec) => { 
    const fragments = containerSpec.fragments || {}; 

    // mock the static container methods 
    Object.assign(component, { getFragment: (fragmentName) => fragments[fragmentName] }); 

    return component; 
    } 
}; 

RelayTestUtils.js

const React = require('react'); 
const ReactDOM = require('react-dom'); 


const RelayTestUtils = { 
    renderContainerIntoDocument(containerElement, relayOptions) { 
    relayOptions = relayOptions || {}; 

    const relaySpec = { 
     forceFetch: jest.genMockFn(), 
     getPendingTransactions: jest.genMockFn().mockImplementation(() => relayOptions.pendingTransactions), 
     hasOptimisticUpdate: jest.genMockFn().mockImplementation(() => relayOptions.hasOptimisticUpdate), 
     route: relayOptions.route || { name: 'MockRoute', path: '/mock' }, 
     setVariables: jest.genMockFn(), 
     variables: relayOptions.variables || {} 
    }; 

    return ReactDOM.render(
     React.cloneElement(containerElement, { relay: relaySpec }), 
     document.createElement('div') 
    ); 
    } 
}; 

export default RelayTestUtils; 

測試是這個樣子,哪裏fragmentData的GraphQL響應的形狀相匹配:

it('changes items',() => { 
    const myContainer = RelayTestUtils.renderContainerIntoDocument(
    <MyContainer { ...fragmentData }/>, 
    { variables: { itemId: 'asdf' } } 
); 
    myContainer.changeItem(); 
    expect(myContainer.props.relay.setVariables).toBeCalled(); 
}); 
+1

也不可能只是'嘲笑'網絡層?與pretender(https://github.com/pretenderjs/pretender)類似,中繼可以實際發送查詢,但不是與服務器交談,而只是獲取模擬數據。 – Markus

+1

@agrauch,你能提供一個例子嗎? –