21

这些天我正在试验 React + Relay + Graphql。不幸的是,我找不到任何简单方便的方法来测试由 Relay Container 包装的 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.updateor的调用this.props.relay.setVariables

我的第一次尝试是使用方法构建RelayTestUtil对象renderContainerIntoDocument我主要基于https://github.com/facebook/relay/blob/master/src/tools/mocks /RelayTestUtils.js , https://github.com/facebook/relay/blob/master/src/legacy /store/ mocks /GraphQLStoreQueryResolver.js和 Relay Container 测试。这使用了非常少的模拟,非常适合测试容器渲染,但对于测试数据更改完全没用。试图监视对Relay.Store.updateand的调用this.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();
});
于 2015-10-02T13:55:38.127 回答
1

我写了一篇关于如何使用 Jest 针对工作中的 GraphQL 后端测试 Relay 的博客文章:https ://medium.com/entria/relay-integration-test-with-jest-71236fb36d44#.an74bdopy

这个 repo https://github.com/sibelius/relay-integration-test包含使用 Relay 测试 react web 和 react native 的示例

于 2016-12-07T18:19:19.290 回答