Rob Moorman
Rob Moorman

Founder, technology consultant, architect and full stack developer
Sep 11


Mock your GraphQL API with Apollo

Build and mock you GraphQL API with graphql-tools as a drop-and-replacement interface for your React applications

In one of our recent projects we use GraphQL as the primary data source. This application is completely build with React (with Redux to keep the data flowing) and uses the awesome react-router module to handle navigation. In this case, we extensively used webpack's dev server to boost our development process.

In this blog post we will instruct how to setup your own mocking server with graphql-tools. We used this mocking server a lot during development as a drop-in-replacement for our production GraphQL API. This is one of the great features GraphQL and their development tools has to offer from the open-source community.

Introspective

As GraphQL is introspective, you can query a GraphQL schema for details about itself. This is very useful as we can easily query the complete schema of our GraphQL API. This introspection query can be obtained from https://github.com/graphql/graphql-js/blob/master/src/utilities/introspectionQuery.js.

If you have already your own GraphQL API running, you can check it out via the explorer or e.g. with curl. In this case, We will query the complete schema of the GitHub v4 API.

GitHub GraphQL Schema

GitHub's GraphQL Schema via the introspection query

Package.json dependencies

First of all, we have to install some dependencies.

yarn install graphql apollo-client react-apollo
yarn install graphql-tools apollo-test-utils --dev

Building the mocking interface

Now we have a complete schema (you must save this to e.g. schema.json) available we can setup the mocking interface. First we have to use this schema.json to create the client interface.

// File: apolloMockSchema.js
import { buildClientSchema } from 'graphql/utilities'
import * as introspectionResult from './schema.json'

export const schema = buildClientSchema(introspectionResult)

With the schema in place, we can use it to create a drop-in-replacement network interface (a networkInterface is required to setup the ApolloClient).

// File: apollo.js
import ApolloClient, { createNetworkInterface } from 'apollo-client'
import { mockNetworkInterfaceWithSchema } from 'apollo-test-utils'
import { buildClientSchema } from 'graphql/utilities'
import { addMockFunctionsToSchema } from 'graphql-tools'
import { schema, mocks } from './apolloMockSchema'

export const getNetworkInterface = () => {
  addMockFunctionsToSchema({ schema, mocks })

  return mockNetworkInterfaceWithSchema({ schema })
}

export const client = new ApolloClient({
  networkInterface: getNetworkInterface(),
})

Mocking more realistic dummy data

A nice feature of the mocking interface is that it generates values for specific schema types. In case e.g. of a string the value Hello world is returned. For lists two items are generated. This is quite handy to see if everything is working properly (haven't got any issues with this mocking schema so far!).

However to use more realistic dummy data while developing components the tooling offers a pretty simple implementation. For every type (these types are defined within your GraphQL API) and query you can additionally setup specific dummy data, e.g. pricing information or random names instead of Hello world values.

Let's extend our mocking schema with some more realistic dummy data:

// File: apolloMockSchema.js
import { buildClientSchema } from 'graphql/utilities'
import * as introspectionResult from './schema.json'

export const schema = buildClientSchema(introspectionResult)

export const mocks = {
  Price: () => ((Math.random() * 100) / 2).toFixed(2),
}

You can read the documentation of graphql-tools to find out more about these mocking features.

Conclusion

We think the mocking interface is very powerful combined with the mocking features graphql-tools has to offer. As we make sure the schema is synced with our production GraphQL API we don't have to think about keeping our client mocks in sync with data from our backends. This gives us the ability to move ridiculously fast during the first phase of development. Switching over from mocking data to production data is just a matter of using the correct networkInterface. Actually, we use, with NODE_ENV=development set, the mocking API and a public facing interface for non-development builds.

As the mocking interface perfectly works with unit- and integration tests (the API doesn't change for your components/containers) we can also easily create more realistic high-order snapshots to make sure everything is working properly by our CI process.


Rob Moorman
Rob Moorman

Founder, technology consultant, architect and full stack developer