Guide on How to Test React Apollo components with Enzyme

Testing React Apollo components with Enzyme

Despite its popularity, React Apollo client has no good documentations on how to do testing for React Apollo components with Enzyme.

The only documentation that I found online for testing React Apollo component is a comment from React Apollo team on GitHub, and it is not using Enzyme.

So how do you test React Apollo components with Enzyme? And perhaps more importantly how do you get access to the inner component wrapped by React Apollo as a higher-order component (HOC) to mock its functions and verify its behaviours?

Method 1: Using React Apollo’s MockedProvider (HOC)

If you are following the guide for React Apollo query when writing your components, you probably have something like this in the file for your component:

By default, this would export the higher-order component wrapped with Apollo’s GraphQL query. This allows the inner component to have access to the query result via  props.data.

If you just want to test the higher-order component with the React Apollo logic, you can use the MockedProvider inside react-apollo/test-utils package. Here is an example of how the test file would look like:

A few things to note here:

  • Mocked Queries: You can mock any number of queries and the responses with MockedProvider. You just need to make sure that they match the queries you send in the   export default graphql(gql`query { ... }`)(MyComponent) statement. There aren’t much documentation on how to use  MockedProvider but there is a gist here with some examples.
  • Inner Component: You can access the inner component via  wrapper.find('MyComponent') and do things like accessing the props. However, you cannot use certain Enzyme helpers such as .state() because they only work on the root component .You can refer to the documentation from Enzyme on how which ones can be used and which ones cannot be used.
  • Enzyme Mount vs Shallow: You can only use mount  here, but not shallow  because using shallow skips the React component life cycles including componentWillReceiveProps, which is used by React Apollo to pass in the response as  props.data.
  • Execution Time: This method is slow (100ms+ for me) because it takes time to do a full render using mount on jsdom.

Method 2: Export Plain Component Separately from HOC

Instead of just exporting the HOC in your component file, you can additionally export the plain component, along with the HOC. An example on how to do that was provided by the React Apollo team in this comment.

Apply this technique to rewrite MyComponent file in method 1, we have:

Notice that we are exporting both MyComponent , and the HOC wrapped by React Apollo.

In order to import both the default export and the named export of the component, you can do:

Where MyComponentWithGQL is the HOC, and MyComponent is the plain component. If you are just importing MyComponent for the test, you can ignore the first part.

With the separately exported plain component, we can test it directly without the MockedProvider wrapper and set the props manually:

Compared to the first method, there are a few key differences:

  • Isolation: Here we are testing the component directly without being wrapped in a HOC, hence the logic is simpler without the need to use MockedProvider. You can also access the component’s state via Enzyme’s .state() helper since the component is the root component.
  • Enzyme Mount or Shallow: This method of testing allows us to use either mount or shallow since we are setting the props manually. Enzyme allows setProps  to trigger componentWillReceiveProps even when using shallow, this makes the tests run faster. If you want to test child components within the component, you can still use mount.
  • Execution Time: This is faster than the first method if you are using shallow, since lifecycle hooks are skipped and child components are not rendered.

 

Conclusion

So that was two ways to test React Apollo components using Enzyme. The test framework I used here is jest, but the idea should be applicable to other frameworks as well.

I personally prefer the second method of testing because it is simpler to write test. However, the first method does allow some form of integration testing for the component, so it might be useful in certain cases as well.


Cover image from https://medium.com/@reyhansofian/react-native-with-react-apollo-df8fd712f129

Leave a Reply