Mocking

Mock your GraphQL data based on a schema.


📣 New in Apollo Server 4: Apollo Server 4 removes both the mocks and mockEntireSchema constructor options. This article has been updated to use the @graphql-tools package to mock data for Apollo Server. For the most up-to-date information on @graphql-tools, we recommend referencing their documentation.

Mocking enables Apollo Server to return simulated data for GraphQL operations based on your server's schema. The strongly-typed nature of a GraphQL API lends itself to mocking, which is an important part of a GraphQL-first development process.

Mocking enables frontend developers to build out and test UI components and features without needing to wait for a full backend implementation. Mocking is also valuable when using a UI tool like Storybook, because you don't need to start a real GraphQL server.

Enabling mocks

To mock data based on your schema start by installing the @graphql-tools/mock and @graphql-tools/schema packages into your dev dependencies:

Bash
1  npm install --save-dev @graphql-tools/mock @graphql-tools/schema

You can combine addMocksToSchema (from @graphql-tools/mock) and makeExecutableSchema (from @graphql-tools/schema) to provide mock data for every field in your server's schema:

TypeScript
1import { ApolloServer } from '@apollo/server';
2import { addMocksToSchema } from '@graphql-tools/mock';
3import { makeExecutableSchema } from '@graphql-tools/schema';
4import { typeDefs } from './schema';
5import { resolvers } from './resolvers';
6
7new ApolloServer({
8  // addMocksToSchema accepts a schema instance and provides
9  // mocked data for each field in the schema
10  schema: addMocksToSchema({
11    schema: makeExecutableSchema({ typeDefs, resolvers }),
12  }),
13});

Mocking logic looks at the type returned by each schema field and returns a default value for that type.

The table below covers the default scalar types and the default mocked values returned for each type:

Type Default Mock Value
Int
Returns a random positive or negative integer.
String
Returns Hello world.
Float
Returns a random positive or negative double-precision floating-point value.
Boolean
Randomly returns either true or false.
ID
Returns a randomized UUID containing a combination of integers and letters.

When using mocks, you don't have to specify resolvers. By default, any resolvers you specify are ignored when you enable mocks. To configure this behavior, see Using existing resolvers with mocks.

Note: If typeDefs has any custom scalar types, you will need to specify what your server should return for those types. You can do this by creating a customized mock with resolvers for each custom scalar type, as described below.

Customizing mocks

In the examples below, we use top-level await calls to start our server asynchronously. Check out our Getting Started guide to see how we configured our project to support this.

For more sophisticated testing, you can customize your mocks to return user-specified data. You can customize your mocks by providing an object that specifies the values to return for different return types.

By default, the functions you define in your mocks take precedence over any currently defined resolvers.

For example, below, both Query.hello and Query.resolved return Hello:

TypeScript
1import { ApolloServer } from '@apollo/server';
2import { startStandaloneServer } from '@apollo/server/standalone';
3import { addMocksToSchema } from '@graphql-tools/mock';
4import { makeExecutableSchema } from '@graphql-tools/schema';
5
6const typeDefs = `#graphql
7  type Query {
8    hello: String
9    resolved: String
10  }
11`;
12
13const resolvers = {
14  Query: {
15    resolved: () => 'Resolved',
16  },
17};
18
19const mocks = {
20  Int: () => 6,
21  Float: () => 22.1,
22  String: () => 'Hello',
23};
24
25const server = new ApolloServer({
26  schema: addMocksToSchema({
27    schema: makeExecutableSchema({ typeDefs, resolvers }),
28    mocks,
29  }),
30});
31
32const { url } = await startStandaloneServer(server, { listen: { port: 4000 } });
33
34console.log(`🚀 Server listening at: ${url}`);

You can also use mocks to define object types and the fields belonging to those object types (much like a resolver map). In the below example, our mocked Person object calls a function returning an object with fields that contain other functions:

TypeScript
1// importing the casual library
2const casual = require('casual');
3
4const mocks = {
5  Person: () => ({
6    name: casual.name,
7    age: () => casual.integer(0, 120),
8  }),
9};

This example uses casual, a fake data generator for JavaScript that returns a different result every time the function 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 lists in mocks

To automate mocking a list, return an array of the desired length. Using [...new Array(n)] is convenient syntax for creating an array that contains n copies of undefined.

TypeScript
1import casual from 'casual';
2
3const mocks = {
4  Person: () => ({
5    // a list of length between 2 and 6, using the "casual" npm module
6    // to generate a random integer
7    friends: [...new Array(casual.integer(2, 6))],
8    // a list of three lists of two items: [[1, 1], [2, 2], [3, 3]]
9    listOfLists: () => [...new Array(3)].map((i) => [...new Array(2)]),
10  }),
11};

Using existing resolvers with mocks

By default, mocks overwrite your server's existing resolvers. To use your server's resolvers while mocking, set the makeExecutableSchema function's preserveResolvers option to true:

TypeScript
1import { ApolloServer } from '@apollo/server';
2import { startStandaloneServer } from '@apollo/server/standalone';
3import { addMocksToSchema } from '@graphql-tools/mock';
4import { makeExecutableSchema } from '@graphql-tools/schema';
5
6const typeDefs = `#graphql
7  type Query {
8    hello: String
9    resolved: String
10  }
11`;
12
13const resolvers = {
14  Query: {
15    resolved: () => 'Resolved',
16  },
17};
18
19const mocks = {
20  Int: () => 6,
21  Float: () => 22.1,
22  String: () => 'Hello',
23};
24
25const server = new ApolloServer({
26  schema: addMocksToSchema({
27    schema: makeExecutableSchema({ typeDefs, resolvers }),
28    mocks,
29    preserveResolvers: true,
30  }),
31});
32
33const { url } = await startStandaloneServer(server, { listen: { port: 4000 } });
34
35console.log(`🚀 Server listening at: ${url}`);

Above, the resolved query now uses its defined resolver, so it returns the string Resolved.

Feedback

Edit on GitHub

Forums