Mocking API responses with React Apollo

Apollo Client and the GraphQL tools that have been made open source within the last years are pretty awesome, the community that is being builded around them is great. However, as with every new technology, there are a lot of things that need to mature and improve.

Documentation on testing is definitely one of the bits that needs a lot of improvements, it isn’t clear what to do, and I personally found myself digging into the source code to understand what to do.

One of the problems I faced was that I wanted to use mock responses when testing my app components, and there are at least two ways of doing this:

The first way is to use graphql-tools. From their docs:

This package allows you to use the GraphQL schema language to build your GraphQL.js schema, and also includes useful schema tools like per-type mocking.

You can use this library together with a custom MockNetworkInterface to return mocked responses to your components:

const { mockServer } = require("graphql-tools");
const { print } = require("graphql/language/printer");

class MockNetworkInterface {
constructor(schema, mocks = {}) {
if (!schema) {
throw new Error('Cannot create Mock Api without specifying a schema');
}
this.mockServer = mockServer(schema, mocks);
}

query(request) {
return this.mockServer.query(print(request.query), request.variables);
}
}

This is nice, and very flexible, with graphql-tools you can do pretty much whatever you do in your actual API.

What I didn’t like about this approach is that you need your schema in sync with the schema defined in your API (you can do this making an instrospection query to your backend), I also found this approach overcomplicates things unnecessarily.

The second (and simpler) approach I found was to use the mockNetworkInterface class, this class is defined in react-apollo/test-utils, you can have a peek on it here.

To use it, you first need to define some Mock Requests (these requests need to be exactly the same your components will make):

const GraphQLMocks = [
{
request: {
query: UserProfileQuery,
variables: {}
},
result: {
data: {
current_user: {
id: 1,
first_name: 'Foo',
last_name: 'Bar',
email: 'foo@example.com'
}
}
}
}
];

The UserProfileQuery is exported from your component:

export const UserProfileQuery = gql`
query userProfile {
current_user {
id
first_name
last_name
email
}
}
`;

And this is how you use it to setup your tests:

import { mockNetworkInterface } from 'react-apollo/test-utils';
import ApolloClient from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
import { mount } from 'enzyme';
import App from '../App.js';
import React from 'react';

const setupTests = () => {
const networkInterface = mockNetworkInterface(...mocks);
// or mockNetworkInterface.apply(null, mocks);
const client = new ApolloClient({
networkInterface,
addTypename: false
});

const wrapper = mount(
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);

return {
wrapper
};
};

It is important that you pass addTypename: false to ApolloClient, otherwise you would have to include a __typename field in all your mocks and queries.

Now any queries your components make will be handled by your mocked responses, you have full control of what you want to return.

And that’s it! I really hope this gets documented in the future and I’ll be looking forward to make mocking and testing easier with React Apollo.

You can see a full example here, the test setup if being created in this file.

I’ll gladly appreciate any comments and suggestions!