React Apollo testing utilities provide mocking capabilities and testing helpers for GraphQL-powered React applications with comprehensive mocking and assertion tools.
Test provider component that mocks GraphQL operations for isolated component testing.
/**
* Provider component for mocking GraphQL operations in tests
* @param props - Configuration for mocked GraphQL responses
* @returns React provider element for testing
*/
function MockedProvider<TSerializedCache = {}>(
props: MockedProviderProps<TSerializedCache>
): React.ReactElement;
interface MockedProviderProps<TSerializedCache = {}> {
mocks?: ReadonlyArray<MockedResponse>;
addTypename?: boolean;
defaultOptions?: DefaultOptions;
cache?: ApolloCache<TSerializedCache>;
resolvers?: Resolvers;
childProps?: object;
children?: React.ReactElement;
link?: ApolloLink;
}
interface MockedResponse {
request: GraphQLRequest;
result?: FetchResult | ResultFunction<FetchResult>;
error?: Error;
delay?: number;
newData?: ResultFunction<FetchResult>;
}Usage Examples:
import React from "react";
import { render, waitFor } from "@testing-library/react";
import { MockedProvider } from "react-apollo";
import { UserProfile } from "./UserProfile";
import { GET_USER_QUERY } from "./queries";
describe("UserProfile", () => {
it("displays user information", async () => {
const mocks = [
{
request: {
query: GET_USER_QUERY,
variables: { id: "1" }
},
result: {
data: {
user: {
id: "1",
name: "John Doe",
email: "john@example.com",
__typename: "User"
}
}
}
}
];
const { getByText } = render(
<MockedProvider mocks={mocks} addTypename={false}>
<UserProfile userId="1" />
</MockedProvider>
);
// Wait for query to resolve
await waitFor(() => {
expect(getByText("John Doe")).toBeInTheDocument();
expect(getByText("john@example.com")).toBeInTheDocument();
});
});
it("handles loading state", () => {
const mocks = [
{
request: {
query: GET_USER_QUERY,
variables: { id: "1" }
},
result: {
data: {
user: {
id: "1",
name: "John Doe",
email: "john@example.com"
}
}
},
delay: 1000 // Simulate slow network
}
];
const { getByText } = render(
<MockedProvider mocks={mocks}>
<UserProfile userId="1" />
</MockedProvider>
);
expect(getByText("Loading...")).toBeInTheDocument();
});
it("handles error state", async () => {
const mocks = [
{
request: {
query: GET_USER_QUERY,
variables: { id: "1" }
},
error: new Error("Failed to fetch user")
}
];
const { getByText } = render(
<MockedProvider mocks={mocks}>
<UserProfile userId="1" />
</MockedProvider>
);
await waitFor(() => {
expect(getByText("Error: Failed to fetch user")).toBeInTheDocument();
});
});
});Creates a mock Apollo Link for testing GraphQL operations with configurable responses.
/**
* Create mock Apollo Link for testing
* @param mocks - Array of mocked responses
* @param addTypename - Whether to add __typename to responses
* @returns Apollo Link for testing
*/
function MockLink(
mocks: ReadonlyArray<MockedResponse>,
addTypename?: boolean
): ApolloLink;
/**
* Create mock link with single operation
* @param mockedResponses - Individual mocked responses
* @returns Apollo Link for testing
*/
function mockSingleLink(...mockedResponses: MockedResponse[]): ApolloLink;Usage Examples:
import { MockLink } from "react-apollo";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
describe("Apollo Client with MockLink", () => {
it("executes queries with mocked responses", async () => {
const mocks = [
{
request: {
query: GET_USERS_QUERY,
variables: { limit: 10 }
},
result: {
data: {
users: [
{ id: "1", name: "Alice", __typename: "User" },
{ id: "2", name: "Bob", __typename: "User" }
]
}
}
}
];
const mockLink = new MockLink(mocks, true);
const client = new ApolloClient({
link: mockLink,
cache: new InMemoryCache()
});
const result = await client.query({
query: GET_USERS_QUERY,
variables: { limit: 10 }
});
expect(result.data.users).toHaveLength(2);
expect(result.data.users[0].name).toBe("Alice");
});
it("handles mutation testing", async () => {
const CREATE_USER_MUTATION = gql`
mutation CreateUser($input: UserInput!) {
createUser(input: $input) {
id
name
email
}
}
`;
const mockLink = mockSingleLink({
request: {
query: CREATE_USER_MUTATION,
variables: {
input: { name: "Charlie", email: "charlie@example.com" }
}
},
result: {
data: {
createUser: {
id: "3",
name: "Charlie",
email: "charlie@example.com",
__typename: "User"
}
}
}
});
const client = new ApolloClient({
link: mockLink,
cache: new InMemoryCache()
});
const result = await client.mutate({
mutation: CREATE_USER_MUTATION,
variables: {
input: { name: "Charlie", email: "charlie@example.com" }
}
});
expect(result.data.createUser.name).toBe("Charlie");
});
});Creates mock Apollo Link specifically for testing GraphQL subscriptions.
/**
* Create mock subscription link for testing real-time operations
* @returns Apollo Link for subscription testing
*/
function MockSubscriptionLink(): ApolloLink;
/**
* Create mock observable link for testing
* @returns Apollo Link for observable testing
*/
function mockObservableLink(): ApolloLink;Usage Examples:
import { MockSubscriptionLink } from "react-apollo";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
describe("Subscription testing", () => {
it("handles subscription data", (done) => {
const COMMENT_SUBSCRIPTION = gql`
subscription OnCommentAdded($postId: ID!) {
commentAdded(postId: $postId) {
id
content
author {
name
}
}
}
`;
const mockLink = new MockSubscriptionLink();
const client = new ApolloClient({
link: mockLink,
cache: new InMemoryCache()
});
// Subscribe to updates
const subscription = client.subscribe({
query: COMMENT_SUBSCRIPTION,
variables: { postId: "1" }
}).subscribe({
next: (result) => {
expect(result.data.commentAdded.content).toBe("Test comment");
done();
},
error: done
});
// Simulate subscription data
mockLink.simulateResult({
result: {
data: {
commentAdded: {
id: "1",
content: "Test comment",
author: { name: "Test User" },
__typename: "Comment"
}
}
}
});
});
});Utility functions for testing GraphQL applications.
/**
* Create Apollo Client instance for testing
* @param config - Optional client configuration
* @returns Configured Apollo Client for tests
*/
function createClient(config?: any): ApolloClient<any>;
/**
* Remove Apollo-specific symbols from data for testing
* @param data - Data object to clean
* @returns Data without Apollo symbols
*/
function stripSymbols(data: any): any;
/**
* Wait utility for async testing
* @param milliseconds - Time to wait in milliseconds
* @returns Promise that resolves after specified time
*/
function wait(milliseconds?: number): Promise<void>;Usage Examples:
import { createClient, stripSymbols, wait } from "react-apollo";
describe("Testing utilities", () => {
it("creates test client", () => {
const client = createClient({
cache: new InMemoryCache(),
resolvers: {
Query: {
user: () => ({ id: "1", name: "Test User" })
}
}
});
expect(client).toBeInstanceOf(ApolloClient);
});
it("strips Apollo symbols from data", () => {
const dataWithSymbols = {
id: "1",
name: "Test",
__typename: "User",
[Symbol.for("apollo.cacheKey")]: "User:1"
};
const cleanData = stripSymbols(dataWithSymbols);
expect(cleanData).toEqual({
id: "1",
name: "Test",
__typename: "User"
});
});
it("waits for async operations", async () => {
const start = Date.now();
await wait(100);
const end = Date.now();
expect(end - start).toBeGreaterThanOrEqual(100);
});
});import React from "react";
import { render, fireEvent, waitFor } from "@testing-library/react";
import { MockedProvider } from "react-apollo";
import { CreateUserForm } from "./CreateUserForm";
describe("CreateUserForm", () => {
it("submits user creation", async () => {
const CREATE_USER = gql`
mutation CreateUser($input: UserInput!) {
createUser(input: $input) {
id
name
email
}
}
`;
const mocks = [
{
request: {
query: CREATE_USER,
variables: {
input: { name: "John Doe", email: "john@example.com" }
}
},
result: {
data: {
createUser: {
id: "1",
name: "John Doe",
email: "john@example.com"
}
}
}
}
];
const { getByLabelText, getByText } = render(
<MockedProvider mocks={mocks}>
<CreateUserForm />
</MockedProvider>
);
fireEvent.change(getByLabelText("Name"), {
target: { value: "John Doe" }
});
fireEvent.change(getByLabelText("Email"), {
target: { value: "john@example.com" }
});
fireEvent.click(getByText("Create User"));
await waitFor(() => {
expect(getByText("User created successfully")).toBeInTheDocument();
});
});
});describe("Error handling", () => {
it("displays network errors", async () => {
const mocks = [
{
request: {
query: GET_USER_QUERY,
variables: { id: "1" }
},
error: new Error("Network error")
}
];
const { getByText } = render(
<MockedProvider mocks={mocks}>
<UserProfile userId="1" />
</MockedProvider>
);
await waitFor(() => {
expect(getByText("Network error")).toBeInTheDocument();
});
});
it("displays GraphQL errors", async () => {
const mocks = [
{
request: {
query: GET_USER_QUERY,
variables: { id: "1" }
},
result: {
errors: [{ message: "User not found" }]
}
}
];
const { getByText } = render(
<MockedProvider mocks={mocks}>
<UserProfile userId="1" />
</MockedProvider>
);
await waitFor(() => {
expect(getByText("User not found")).toBeInTheDocument();
});
});
});