Mocking

Mock your GraphQL data based on a schema.


The strongly-typed nature of a GraphQL API lends itself extremely well to mocking. This is an important part of a GraphQL-First development process, because it enables frontend developers to build out UI components and features without having to wait for a backend implementation.

Even when the UI is already built, it can let you test your UI without waiting on slow database requests, or build out a component harness using a tool like Storybook without needing to start a real GraphQL server.

Default mock example

This example demonstrates mocking a GraphQL schema with just one line of code, using apollo-server's default mocking logic.

JavaScript
1const { ApolloServer, gql } = require('apollo-server');
2
3const typeDefs = gql`
4  type Query {
5    hello: String
6  }
7`;
8
9const server = new ApolloServer({
10  typeDefs,
11  mocks: true,
12});
13
14server.listen().then(({ url }) => {
15  console.log(`🚀 Server ready at ${url}`)
16});

Note: If typeDefs has custom scalar types, resolvers must still contain the serialize, parseValue, and parseLiteral functions

Mocking logic simply looks at the type definitions and returns a string where a string is expected, a number for a number, etc. This provides the right shape of result. By default, when using mocks, any existing resolvers are ignored. See the "Using existing resolvers with mocks" section below for more info on how to change this behavior.

For more sophisticated testing, mocks can be customized to a particular data model.

Customizing mocks

In addition to a boolean, mocks can be an object that describes custom mocking logic, which is structured similarly to resolvers with a few extra features aimed at mocking. Namely mocks accepts functions for specific types in the schema that are called when that type is expected. By default, the functions in mocks will overwrite the resolvers in resolvers. In this example hello and resolved will both return 'Hello'.

JavaScript
1const { ApolloServer, gql } = require('apollo-server');
2
3const typeDefs = gql`
4  type Query {
5    hello: String
6    resolved: String
7  }
8`;
9
10const resolvers = {
11  Query: {
12    resolved: () => 'Resolved',
13  },
14};
15
16const mocks = {
17  Int: () => 6,
18  Float: () => 22.1,
19  String: () => 'Hello',
20};
21
22const server = new ApolloServer({
23  typeDefs,
24  resolvers,
25  mocks,
26});
27
28server.listen().then(({ url }) => {
29  console.log(`🚀 Server ready at ${url}`)
30});

Similarly to resolvers, mocks allows the description of object types with the fields. Take note that the value corresponding to Person is a function that returns an object that contains fields pointing at more functions:

JavaScript
1const mocks = {
2  Person: () => ({
3    name: casual.name,
4    age: () => casual.integer(0, 120),
5  }),
6};

The previous example uses casual , a fake data generator for JavaScript, which returns a different result every time the field is called. In other scenarios, such as testing, a collection of fake objects or a generator that always uses a consistent seed are often necessary to provide consistent data.

Using MockList in resolvers

To automate mocking a list, return an instance of MockList:

JavaScript
1const { MockList } = require('apollo-server');
2
3const mocks = {
4  Person: () => ({
5    // a list of length between 2 and 6 (inclusive)
6    friends: () => new MockList([2,6]),
7    // a list of three lists each with two items: [[1, 1], [2, 2], [3, 3]]
8    listOfLists: () => new MockList(3, () => new MockList(2)),
9  }),
10};

In more complex schemas, MockList is helpful for randomizing the number of entries returned in lists.

For example, this schema:

GraphQL
1type Query {
2  people: [Person]
3}
4
5type Person {
6  name: String
7  age: Int
8}

By default, the people field will always return 2 entries. To change this, we can add a mock resolver that returns MockList:

JavaScript
1const mocks = {
2  Query: () =>({
3    people: () => new MockList([0, 12]),
4  }),
5};

Now the mock data will contain between zero and 12 summary entries.

Accessing arguments in mock resolvers

The mock functions on fields are actually just GraphQL resolvers, which can use arguments and context:

JavaScript
1const mocks = {
2  Person: () => ({
3    // the number of friends in the list now depends on numPages
4    paginatedFriends: (parent, args, context, info) => new MockList(args.numPages * PAGE_SIZE),
5  }),
6};

For some more background and flavor on this approach, read the "Mocking your server with one line of code" article on the Apollo blog.

Using existing resolvers with mocks

The default behavior for mocks is to overwrite the resolvers already present in the schema. To keep the existing resolvers, set the mockEntireSchema option to false.

Note: mocking resolvers will not work if the mocks option is false, even if mockEntireSchema is true.

JavaScript
1const { ApolloServer, gql } = require('apollo-server');
2
3const typeDefs = gql`
4  type Query {
5    hello: String
6    resolved: String
7  }
8`;
9
10const resolvers = {
11  Query: {
12    resolved: () => 'Resolved',
13  },
14};
15
16const mocks = {
17  Int: () => 6,
18  Float: () => 22.1,
19  String: () => 'Hello',
20};
21
22const server = new ApolloServer({
23  typeDefs,
24  resolvers,
25  mocks,
26  mockEntireSchema: false, // highlight-line
27});
28
29server.listen().then(({ url }) => {
30  console.log(`🚀 Server ready at ${url}`)
31});

Mocking a schema using introspection

The GraphQL specification allows clients to introspect the schema with a special set of types and fields that every schema must include. The results of a standard introspection query can be used to generate an instance of GraphQLSchema which can be mocked as explained above.

This helps when you need to mock a schema defined in a language other than JS, for example Go, Ruby, or Python.

To convert an introspection query result to a GraphQLSchema object, you can use the buildClientSchema utility from the graphql package.

JavaScript
1const { buildClientSchema } = require('graphql');
2const introspectionResult = require('schema.json');
3const { ApolloServer } = require('apollo-server');
4
5const schema = buildClientSchema(introspectionResult.data);
6
7const server = new ApolloServer({
8  schema,
9  mocks: true,
10});
11
12server.listen().then(({ url }) => {
13  console.log(`🚀 Server ready at ${url}`)
14});

API

Under the hood, Apollo Server uses a library for building GraphQL servers called graphql-tools. The mocking functionality is provided by the function addMockFunctionsToSchema . The mocks object is passed directly to the function, and preserveResolvers is the inverse of mockEntireSchema. MockList is exported directly from the graphql-tools library.