Integration testing of Relay containers with Jest

2019-06-01 16:22发布

问题:

I'd like to implement the integration testing of my Relay containers against a running GraphQL backend server. I'm going to use Jest for this. I'd like to say that unit testing of React components works well as expected with my Jest setup. Here's what I have in the package.json for the Jest:

"jest": {
    "moduleFileExtensions": [
      "js",
      "jsx"
    ],
    "moduleDirectories": [
      "node_modules",
      "src"
    ],
    "moduleNameMapper": {
      "^.+\\.(css|less)$": "<rootDir>/src/styleMock.js",
      "^.+\\.(gif|ttf|eot|svg|png)$": "<rootDir>/src/fileMock.js"
    },
    "unmockedModulePathPatterns": [
      "<rootDir>/node_modules/react/",
      "<rootDir>/node_modules/react-dom/",
      "<rootDir>/node_modules/react-addons-test-utils/",
      "<rootDir>/node_modules/react-relay/"
    ]
}

Here's the .babelrc I'm using:

{
  "presets": ["es2015", "react", "stage-0"],
  "plugins": ["./babelRelayPlugin.js"]
}

Here's the test itself. It must make a request to `http://localhost:10000/q' GraphQL endpoint to fetch a simple piece that represents the info about the current user ('me').

jest.disableAutomock();

import React from 'react';
import Relay from 'react-relay';
import TestUtils from 'react-addons-test-utils';
import RelayNetworkDebug from 'react-relay/lib/RelayNetworkDebug';

RelayNetworkDebug.init();
Relay.injectNetworkLayer(
  new Relay.DefaultNetworkLayer('http://localhost:10000/q')
);

describe('Me', () => {
  it('can make request to /q anyway', () => {
    class RootRoute extends Relay.Route {
      static queries = {
        root: (Component) => Relay.QL`
            query {
                root {
                    ${Component.getFragment('root')}
                }
            }
        `,
      };

      static routeName = 'RootRoute';
    }

    class AppRoot extends React.Component {
      static propTypes = {
        root: React.PropTypes.object,
      };

      render() {
        expect(this.props.root).not.toBe(null);
        expect(this.props.root.me).not.toBe(null);
        expect(this.props.root.me.firstName).not.toBe(null);
        expect(this.props.root.me.authorities[0]).not.toBe(null);
        expect(this.props.root.me.authorities[0].authority).toEqual('ROLE_ANONYMOUS_AAA');

        return (
          <div>
            {this.props.root.me.firstName}
          </div>
        );
      }
    }

    const AppContainer = Relay.createContainer(AppRoot, {
      fragments: {
        root: () => Relay.QL`
            fragment on Root {
                me {
                    firstName
                    email
                    authorities {
                        authority
                    }
                }
            }
        `,
      },
    });

    const container = TestUtils.renderIntoDocument(
      <div>
        <Relay.RootContainer Component={AppContainer} route={new RootRoute()} />
      </div>
    );

    expect(container).not.toBe(null);
  });
});

The problem is that the test passes. But in my opinion it must fail at this line inside the render() expect(this.props.root.me.authorities[0].authority).toEqual('ROLE_ANONYMOUS_AAA');. It seems like the render() method is not executed at all.

I'm running Jest like this

./node_modules/.bin/jest

Does this all suppose to work at all?

Thank you.

回答1:

This is possible, take a look on the code: https://github.com/sibelius/relay-integration-test

and on my blog post: https://medium.com/entria/relay-integration-test-with-jest-71236fb36d44#.ghhvvbbvl

The missing piece is that you need to polyfill XMLHttpRequest to make it work with React Native.

And you need to polyfill fetch for React web