Mocking
Mock your GraphQL data based on a schema.
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.
Using default mocks
You can turn on Apollo Server's default mocking logic by passing mocks: true
to the ApolloServer constructor:
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});
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 |
---|---|
|
Returns a random positive or negative integer. |
|
Returns |
|
Returns a random positive or negative double-precision floating-point value. |
|
Randomly returns either |
|
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
For more sophisticated testing, you can customize your mocks to return user-specified data.
Instead of providing a boolean to the mocks
option, you can provide an object that defines custom mocking logic. This enables you to specify values to return for different return types.
By default, the functions in mocks
take precedence over any currently defined resolvers. In the below example, both Query.hello
and Query.resolved
return Hello
.
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});
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, note that our mocked Person
object calls a function returning an object with fields that contain other functions:
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};
The previous 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
.
1const casual = require('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
The default behavior for mocks is to overwrite the resolvers already present in the schema. To use your server's existing resolvers while mocking, set the mockEntireSchema
option to false
.
Note: Mocking resolvers doesn't work if the
mocks
option isfalse
, even ifmockEntireSchema
istrue
.
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,
27});
28
29server.listen().then(({ url }) => {
30 console.log(`🚀 Server ready at ${url}`)
31});
Running the above example with the mockEntireSchema
option set to false
, the resolved
field now returns the string Resolved
.
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
that can be mocked as explained above.
This helps when you need to mock a schema defined in a language besides JavaScript.
To convert an introspection query result to a GraphQLSchema
object, you can use the buildClientSchema
utility from the graphql
package.
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's mocking functionality is provided by the function addMocksToSchema
from the @graphql-tools/mock
package. The mocks
object is passed directly to the addMocksToSchema
function, and preserveResolvers
is the inverse of mockEntireSchema
.
Apollo Server does not support all of the arguments to addMocksToSchema
, such as resolvers
. To use features of @graphql-tools/mock
that aren't supported by Apollo Server, you can install and use @graphql-tools/mock
directly:
1const { addMocksToSchema } = require('@graphql-tools/mock')
2const { makeExecutableSchema } = require('@graphql-tools/schema');
3
4const server = new ApolloServer({
5 schema: addMocksToSchema({
6 schema: makeExecutableSchema({ typeDefs, resolvers }),
7 }),
8});