Testing with Apollo Federation
Unit, integration, end-to-end, composition, and component and operation testing
💡 TIP
If you're an enterprise customer looking for more material on this topic, try the
Not an enterprise customer?
Testing in GraphQL may seem like it can involve more steps, but that is because your GraphQL architecture can involve many areas of your tech stack, from your frontend with Apollo Client to a backend with Apollo Server, or your infrastructure with your Apollo Router to the individual subgraphs in your supergraph. In practice, all these areas should be properly tested the same way if we were using any other API technology, but often the testing across boundaries like teams or applications can involve some new steps. By the end of this guide you should have:
- Unit testingin individual subgraphs
- Integration testingfor the individual subgraphs
- End-to-end testingfor your entire supergraph
- Composition testingfor supergraph schema generation
- Component and operation testingfor your clients
Unit testing
We recommend creating unit tests for each of your subgraph server resolvers. Resolvers are the code that gets called for each type or field in your schema, which creates a natural boundary to test in isolation. When doing so, we recommend mocking as much data as possible using a package like @faker-js/faker
Using @faker-js/faker
to mock a return value in jest
looks something like the following:
import { faker } from "@faker-js/faker";const testUser = {userId: faker.datatype.uuid(),username: faker.internet.userName(),email: faker.internet.email(),avatar: faker.image.avatar(),password: faker.internet.password(),birthdate: faker.date.birthdate(),registeredAt: faker.date.past(),};const mockedFunction = jest.fn().mockReturnValue(testUser);
Reference resolvers in unit tests
The __resolveReference
function (also known as a
Integration testing
Integration tests for subgraphs should start up a single subgraph and send operations to the schema in a mocked or test environment. To test just the subgraph in isolation, validate all the fields giving special focus to the top-level fields in your queries and mutations, and use all permutations of your inputs to check your schema matches your resolvers.
Entity resolvers in integration tests
Depending on your schema and operations, the resulting _entities
@key
).
This looks like the following:
query GetEntities($representations: [_Any!]!) {_entities(representations: $representations) {... on User {firstName}}}
with the following input
{"representations": [{"__typename": "User","id": "5"}]}
To see more examples on how to test these operations, see Query._entities
End-to-end testing
Follow these best practices when creating end-to-end tests for your supergraph:
- Run all your subgraphs and router in a test environment with either mocked or test data
- Use example operations that are actually executed against your supergraph.
- You can view the details of recent operations in GraphOS Studio.
- Avoid boilerplate or randomly generated operations, because these don't reflect actual traffic.
- If you are not in production yet, we suggest making these tests as close to what you think they will be as possible.
- Make sure to include operation that span multiple subgraphs to validate entity resolvers
- Use variables to ensure high operation cardinality.
- If your test operations don't use any GraphQL variables (or if you use the same variable values across executions), your supergraph is likely to return cached data. This circumvents large portions of execution logic, limiting test effectiveness.
- By using a variety of operations and variable values, you help make sure that your tests result in minimal cache hits.
Composition testing
Composition testing is specific to a federated architecture. It involves testing that your subgraph schemas successfully rover subgraph check
Component and operation testing
Fortunately, clients are not actually aware of when they are using a Federated GraphQL API versus a non-Federated one so the testing best practices remain the same. Our schema can provide a convenient layer to