Integration tests check if different parts of your GraphQL server work well together. Using a test server helps you test safely without affecting real data.
Integration tests with test server in GraphQL
Start learning this pattern below
Jump into concepts and practice - no test required
import { createTestClient } from 'apollo-server-testing'; import { ApolloServer } from 'apollo-server'; const server = new ApolloServer({ typeDefs, resolvers }); const { query, mutate } = createTestClient(server); // Use query({ query: YOUR_QUERY }) or mutate({ mutation: YOUR_MUTATION }) to test
You create a test server instance with your schema and resolvers.
Use query to test queries and mutate to test mutations.
const GET_USER = gql` query GetUser($id: ID!) { user(id: $id) { id name } } `; const res = await query({ query: GET_USER, variables: { id: "1" } });
const ADD_USER = gql` mutation AddUser($name: String!) { addUser(name: $name) { id name } } `; const res = await mutate({ mutation: ADD_USER, variables: { name: "Alice" } });
This program creates a simple GraphQL test server with a user list. It tests adding a user and then fetching that user by ID.
import { ApolloServer, gql } from 'apollo-server'; import { createTestClient } from 'apollo-server-testing'; // Define schema const typeDefs = gql` type User { id: ID! name: String! } type Query { user(id: ID!): User } type Mutation { addUser(name: String!): User } `; // In-memory data const users = []; let idCount = 1; // Resolvers const resolvers = { Query: { user: (_, { id }) => users.find(u => u.id === id), }, Mutation: { addUser: (_, { name }) => { const user = { id: String(idCount++), name }; users.push(user); return user; }, }, }; // Create test server const server = new ApolloServer({ typeDefs, resolvers }); const { query, mutate } = createTestClient(server); // Test adding a user (async () => { const ADD_USER = gql` mutation AddUser($name: String!) { addUser(name: $name) { id name } } `; const resAdd = await mutate({ mutation: ADD_USER, variables: { name: "Bob" } }); // Test querying the user const GET_USER = gql` query GetUser($id: ID!) { user(id: $id) { id name } } `; const resGet = await query({ query: GET_USER, variables: { id: resAdd.data.addUser.id } }); console.log(JSON.stringify(resAdd.data)); console.log(JSON.stringify(resGet.data)); })();
Integration tests run your real schema and resolvers, so they catch more issues than unit tests.
Use an in-memory database or mock data to keep tests fast and isolated.
Always clean or reset data between tests to avoid interference.
Integration tests check if your GraphQL server parts work together correctly.
Use a test server to safely run queries and mutations without affecting real data.
Write tests for both queries and mutations to cover your API fully.
Practice
Solution
Step 1: Understand the role of a test server
A test server is a safe environment that mimics the real server but does not affect actual data.Step 2: Identify the purpose in integration tests
Integration tests use the test server to check if queries and mutations work together correctly without risk.Final Answer:
To run queries and mutations safely without affecting real data -> Option BQuick Check:
Test server = safe testing environment [OK]
- Thinking test server speeds up production
- Confusing test server with permanent database replacement
- Assuming test server auto-generates data
Solution
Step 1: Recall Apollo Server setup
Apollo Server requires creating an instance with typeDefs and resolvers, then calling start() before listen().Step 2: Identify correct method to start server
The correct method to start the server is await server.start(); before running listen().Final Answer:
const server = new ApolloServer({ typeDefs, resolvers }); await server.start(); -> Option DQuick Check:
Use server.start() before listen() [OK]
- Calling listen() without starting server
- Using incorrect constructor syntax
- Assuming server.run() or startServer() exist
const result = await server.executeOperation({ query: `query { user(id: 1) { name } }` }); console.log(result.data.user.name);What will be printed if the user with id 1 has the name "Alice"?Solution
Step 1: Understand executeOperation result
executeOperation returns an object with data containing the query result if successful.Step 2: Check the query and expected data
The query requests user with id 1 and its name. If user exists with name "Alice", result.data.user.name will be "Alice".Final Answer:
"Alice" -> Option CQuick Check:
Query result matches user name "Alice" [OK]
- Expecting undefined if user exists
- Confusing null with undefined
- Assuming error thrown instead of null result
const result = await server.executeOperation({ query: `mutation { addUser(name: "Bob") { id } }` });What is the most likely cause?Solution
Step 1: Check mutation usage in test
executeOperation supports mutations, so that is not the issue.Step 2: Verify mutation name and schema
If mutation name addUser is not defined in the schema, the server throws an error.Final Answer:
The mutation name is incorrect or not defined in schema -> Option AQuick Check:
Mutation must exist in schema to run [OK]
- Thinking executeOperation can't run mutations
- Forgetting to await executeOperation
- Confusing query and mutation types
Solution
Step 1: Understand integration test flow
Integration tests verify that mutations affect data and queries reflect those changes.Step 2: Correct test sequence
First run mutation to add user, then query to fetch user, then compare results to confirm correctness.Final Answer:
Run mutation with executeOperation, then run query with executeOperation, check query result matches mutation data -> Option AQuick Check:
Mutation then query to verify changes [OK]
- Running query before mutation
- Running mutation and query in parallel without order
- Skipping query test after mutation
