Integration testing
Utilities for testing Apollo Server
Testing apollo-server
can be done in many ways. One simple way is to use ApolloServer's executeOperation
method to directly execute a GraphQL operation without going through a full HTTP operation.
executeOperation
Integration testing a GraphQL server means testing many things. apollo-server
has a request pipeline that can support many plugins that can affect the way an operation is executed. The executeOperation
method provides a single hook to run operations through the request pipeline, enabling the most thorough tests possible without starting up an HTTP server.
1const server = new ApolloServer(config);
2
3const result = await server.executeOperation({
4 query: GET_USER,
5 variables: { id: 1 }
6});
7expect(result.errors).toBeUndefined();
8expect(result.data?.user.name).toBe('Ida');
For example, you can set up a full server with your schema and resolvers and run an operation against it.
1it('fetches single launch', async () => {
2 const userAPI = new UserAPI({ store });
3 const launchAPI = new LaunchAPI();
4
5 // create a test server to test against, using our production typeDefs,
6 // resolvers, and dataSources.
7 const server = new ApolloServer({
8 typeDefs,
9 resolvers,
10 dataSources: () => ({ userAPI, launchAPI }),
11 context: () => ({ user: { id: 1, email: 'a@a.a' } }),
12 });
13 await server.start();
14
15 // mock the dataSource's underlying fetch methods
16 launchAPI.get = jest.fn(() => [mockLaunchResponse]);
17 userAPI.store = mockStore;
18 userAPI.store.trips.findAll.mockReturnValueOnce([
19 { dataValues: { launchId: 1 } },
20 ]);
21
22 // run query against the server and snapshot the output
23 const res = await server.executeOperation({ query: GET_LAUNCH, variables: { id: 1 } });
24 expect(res).toMatchSnapshot();
25});
This is an example of a full integration test being run against a test instance of apollo-server
. This test imports the important pieces to test (typeDefs
, resolvers
, dataSources
) and creates a new instance of apollo-server
.
The example above shows writing a test-specific context
function which provides data directly instead of calculating it from the request context. If you'd like to use your server's real context
function, you can pass a second argument to executeOperation
which will be passed to your context
function as its argument. You will need to put together an object with the middleware-specific context fields yourself.
You can use executeOperation
to execute queries and mutations. Because the interface matches the GraphQL HTTP protocol, you specify the operation text under the query
key even if the operation is a mutation. You can specify query
either as a string or as a DocumentNode
(an AST created by the gql
tag).
In addition to query
, the first argument to executeOperation
can take operationName
, variables
, extensions
, and http
keys.
Note that errors in parsing, validating, and executing your operation are returned in the errors
field of the result (just like in a GraphQL response) rather than thrown.
createTestClient
and apollo-server-testing
There is also a package called apollo-server-testing
which exports a function createTestClient
which wraps executeOperation
. This API does not support the second context-function-argument argument, and doesn't provide any real advantages over calling executeOperation
directly. It is deprecated and will no longer be published with Apollo Server 3.
We recommend that you replace this code:
1const { createTestClient } = require('apollo-server-testing');
2
3const { query, mutate } = createTestClient(server);
4
5await query({ query: QUERY });
6await mutate({ mutation: MUTATION });
with
1await server.executeOperation({ query: QUERY });
2await server.executeOperation({ query: MUTATION });
End-to-end testing
Instead of bypassing the HTTP layer, you may just want to fully run your server and test it with a real HTTP client.
Apollo Server doesn't have any built-in support for this. You can combine any HTTP or GraphQL client such as supertest
or Apollo Client's HTTP Link to run operations against your server. There are also community packages available such as apollo-server-integration-testing
which provides an API similar to the deprecated apollo-server-testing
package which uses mocked Express request and response objects.