21

最近、React + Relay + Graphql を試しています。残念ながら、リレー コンテナーでラップされた React コンポーネントをテストする簡単で便利な方法が見つかりません。

基本的には、TDDに沿ってこれらの目標を達成したいと考えています。

  1. コンテナをレンダリングしてその内容をテストします。
  2. 変数を変更し、コンテンツでその変更をテストします。

React + Flux と比較すると、React + Relay はブラック ボックス、つまり宣言型に似ています。

Relay.createContainer をモックして Relay をバイパスし、単に React コンポーネントをテストするだけの人がいます。リレー部分が覆われておらず、テストによってこの部分 を駆動する方法はありません。https://github.com/facebook/relay/issues/161

また、Relay のテスト ケースを読み、モック コンテナーをレンダリングするのは非常に面倒です。 https://github.com/facebook/relay/blob/master/src/tools/mocks/RelayTestUtils.js _ _

解決策を共有できれば、本当に感謝しています。

ありがとう!

4

2 に答える 2

12

Flux アプリケーションのコンポーネントと同じように、Relay コンテナーをテストしようとしています。具体的には、特定の状態と小道具に対して正しいコンテンツをレンダリングし、適切な場所でデータを変更するメソッドを呼び出すことを確認したいと考えています。Flux では、これはアクション作成者への呼び出しであり、Relay では、Relay.Store.updateまたはへの呼び出しthis.props.relay.setVariablesです。

私の最初の試みはRelayTestUtil、メソッドを使用してオブジェクトを構築することでしたrenderContainerIntoDocumenthttps://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.updateandの呼び出しをスパイしようとしthis.props.relay.setVariablesたり、データの変更をモックしたりすることは、価値がある以上に面倒になりました。

__mocks__\react-relay.jsRelay を完全にモック化するために追加し、より単純なバージョンの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();
});
于 2015-10-02T13:55:38.127 に答える