Docs
Launch GraphOS Studio

Mocking schema capabilities

Start on client-side features before your server supports them


If your GraphQL server doesn't yet support a that your client will use, you can still start building against that by mocking its behavior within the client.

For example, let's say we want to add a feature to the Space app from the full-stack quickstart course. Specifically, we want to display a description of the rocket used for each launch. To support this functionality on the server side, we'll add a description to our 's Rocket type:

type Rocket {
id: ID!
name: String
type: String
description: String # field not yet supported
}

But what if our back-end team isn't finished adding support for the description ? By mocking the 's behavior, we can still start developing the feature in our client. To do so, we'll follow the steps below.

Our client application can define a client-side schema that extends types from our server, or even defines entirely new types. The syntax is identical to server-side definitions.

Although a client-side isn't required for mocking, it helps team members understand your app's local capabilities. It also unlocks powerful local state support in tools like the Apollo Client Devtools and the Apollo extension for VS Code.

This client-side extends the Rocket type to add a description (make sure to name the typeDefs as shown):

index.js
const typeDefs = gql`
extend type Rocket {
description: String
}
`;

We can then provide this to the ApolloClient constructor, like so:

index.js
const client = new ApolloClient({
uri: 'http://localhost:4000/graphql',
cache: new InMemoryCache(),
typeDefs
});

2. Define a read function

Our client app doesn't yet know how to populate the Rocket.description . To fix this, we can define a read function for the . The Apollo Client cache calls this function whenever the is queried, and the function's return value is used as the 's value.

Let's define our read function in the configuration object we provide to the InMemoryCache constructor:

index.js
const cache = new InMemoryCache({
typePolicies: {
Rocket: {
fields: {
description: {
read() { // Read function for Rocket.description
return 'Placeholder rocket description';
}
},
},
},
},
});

This enables us to query the , but we might not want to show the same boilerplate description for every rocket. To add variety to our mocked output, we can use a library like faker.js:

index.js
import { faker } from "@faker-js/faker";
// Returns 1 or 2 sentences of Lorem Ipsum
const oneOrTwoSentences = () =>
faker.lorem.sentences(Math.random() < 0.5 ? 1 : 2);

We can then update our read function like so:

// (within InMemoryCache constructor)
read() {
return oneOrTwoSentences();
}

Make sure to include libraries like faker.js only in your development build, because they can needlessly increase your production bundle size.

3. Query with the @client directive

We're ready to execute a query that includes our new . Here's an abridged GET_LAUNCH_DETAILS query from the full-stack quickstart with our description added:

export const GET_LAUNCH_DETAILS = gql`
query LaunchDetails($launchId: ID!) {
launch(id: $launchId) {
site
rocket {
type
description @client
}
}
}
`;

Notice that this includes the @client . This tells Apollo Client not to include description in the query it sends to our server. This is important for two related reasons:

  • The description is populated entirely locally, so including it in network requests isn't helpful.
  • The description isn't in our server-side yet, so including it will produce a GraphQL error.

We can now execute this query in a component with the useQuery hook as usual:

export default function LaunchDetails({ launchId }) {
const { data } = useQuery(GET_LAUNCH_DETAILS, { variables: { rocketId } });
return (
<div>
<p>Rocket Type: {data.launch.rocket.type}</p>
<p>Description: {data.launch.rocket.description}</p>
</div>
);
}

4. Use live data when ready

When your server's support for the Rocket.description is ready, you can begin using it by doing the following:

  1. Remove the @client from description in every query that includes it.
  2. Remove the 's read function (or modify the function so that it uses the current cached value instead of a random string).

For more information on the Apollo Client features used here, see the following:

Previous
Testing React components
Next
Reducing bundle size
Edit on GitHubEditForumsDiscord