reactjs - Relay + React 的测试策略

标签 reactjs tdd graphql relayjs

这些天我正在尝试 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

如果您能分享您的解决方案,我将非常感激。

谢谢!

最佳答案

我一直在尝试测试 Relay 容器,就像测试 Flux 应用程序中的组件一样。具体来说,我想确保它们为给定的状态和 Prop 呈现正确的内容,并且它们调用方法来在适当的位置更改数据;在 Flux 中,这是对 Action 创建者的调用,在 Relay 中,这是对 Relay.Store.update 的调用或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.Store.update的电话和this.props.relay.setVariables ,或者模拟数据更改,变得比其值(value)更麻烦。

我决定添加__mocks__\react-relay.js完全模拟 Relay 并使用 RelayTestUtils.renderContainerIntoDocument 的更简单版本将 Relay 属性注入(inject)到容器中。我对这个解决方案并不完全满意,但它目前似乎有效。

__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();
});

关于reactjs - Relay + React 的测试策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32760418/

相关文章:

reactjs - 前端和仪表板的 React Redux 文件夹结构

typescript - Chai 期望使用 Typescript 抛出与相同异常不匹配的异常

unit-testing - 在进行单元测试时,100% 的代码覆盖率真的是一件好事吗?

graphql - 如何防止基于选择集运行解析器?

python - 无法在 python graphql 框架中启用 CORS/允许 header - ariadne

javascript - React 组件上的句柄点击

javascript - 在返回方法中访问查询

javascript - 从语义 ui react 下拉列表中选择的值在选择时不出现

laravel - Laravel:如何在PhpUnit上启用stacktrace错误

javascript - 停止继电器: Query Renderer in reloading data for certain setStates