简体   繁体   English

Relay + React的测试策略

[英]Testing strategy on Relay + React

I am experimenting with React + Relay + Graphql these days. 这些天我正在尝试使用React + Relay + Graphql。 Unfortunately, I cannot find any easy and convenient way to test React component wrapped by Relay Container. 不幸的是,我找不到任何简单方便的方法来测试Relay Container包装的React组件。

Basically, I would like to achieve these goals along TDD, 基本上,我想沿着TDD实现这些目标,

  1. Render a container and test its content, 渲染容器并测试其内容,
  2. Change variables and test its changes on content. 更改变量并测试其对内容的更改。

Compared with React + Flux, React + Relay is more like black box, or, declarative. 与React + Flux相比,React + Relay更像是黑盒子,或者说是声明式的。

I can see people mock Relay.createContainer to bypass Relay and merely test React Component. 我可以看到人们模拟Relay.createContainer来绕过Relay并仅仅测试React Component。 It leaves the Relay part uncovered and there is no way to drive this part by testing. 它使继电器部分不被覆盖,并且无法通过测试来驱动该部件。 https://github.com/facebook/relay/issues/161 https://github.com/facebook/relay/issues/161

Also, I read through test cases of Relay and its really tedious to render a mock container. 另外,我阅读了Relay的测试用例,并且渲染一个模拟容器真的很乏味。 https://github.com/facebook/relay/blob/master/src/tools/ mocks /RelayTestUtils.js https://github.com/facebook/relay/blob/master/src/tools/ mocks /RelayTestUtils.js

I will be really grateful if you can share you solution. 如果您能与我分享解决方案,我将非常感激。

Thanks! 谢谢!

I've been trying to test Relay containers like I would components in a Flux application. 我一直在尝试像Flux应用程序中的组件一样测试Relay容器。 Specifically, I want to make sure that they render the correct content for a given state and props and that they call methods to change data in appropriate places; 具体来说,我想确保它们为给定的状态和道具呈现正确的内容,并且他们调用方法来在适当的位置更改数据; in Flux this is a call to an action creator, in Relay this is a call to Relay.Store.update or this.props.relay.setVariables . 在Flux中,这是对动作创建者的调用,在Relay中,这是对Relay.Store.updatethis.props.relay.setVariables的调用。

My first attempt was to build a RelayTestUtil object with a renderContainerIntoDocument method. 我的第一次尝试是使用renderContainerIntoDocument方法构建一个RelayTestUtil对象。 I based it heavily on 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 , and the Relay Container tests. 我根据它在很大程度上对https://github.com/facebook/relay/blob/master/src/tools/ 嘲笑 /RelayTestUtils.jshttps://github.com/facebook/relay/blob/master/src/legacy / store / mocks /GraphQLStoreQueryResolver.js和Relay Container测试。 This used very minimal mocking and was great for testing container rendering but was completely useless for testing data changes. 这使用非常小的模拟,非常适合测试容器渲染,但对于测试数据更改完全没用。 Trying to spy on calls to Relay.Store.update and this.props.relay.setVariables , or to mock data changes, became more trouble than it was worth. 试图窥探对Relay.Store.updatethis.props.relay.setVariables调用,或模拟数据更改,变得比它的价值更麻烦。

I settled on adding __mocks__\\react-relay.js to completely mock Relay and using simpler version of RelayTestUtils.renderContainerIntoDocument to inject Relay properties into a container. 我决定将__mocks__\\react-relay.js到完全模拟Relay并使用更简单版本的RelayTestUtils.renderContainerIntoDocument将Relay属性注入容器。 I'm not entirely satisfied with this solution, but it seems to work for now. 我对这个解决方案并不完全满意,但它现在似乎有效。

__mocks__\\react-relay.js : __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 : 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;

Tests look something like this, where fragmentData matches the shape of the GraphQL response: 测试看起来像这样,其中fragmentData匹配GraphQL响应的形状:

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

I've wrote a blog post of how to test Relay using Jest against a working GraphQL backend: https://medium.com/entria/relay-integration-test-with-jest-71236fb36d44#.an74bdopy 我写了一篇关于如何使用Jest对正在运行的GraphQL后端测试Relay的博客文章: https ://medium.com/entria/relay-integration-test-with-jest-71236fb36d44#.an74bdopy

This repo https://github.com/sibelius/relay-integration-test contains examples of testing react web and react native using Relay 这个repo https://github.com/sibelius/relay-integration-test包含测试反应网并使用Relay进行原生反应的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM