Mocking your GraphQL API
Mocking your GraphQL API is a common practice when developing and testing your application. It allows you to simulate the behavior of your API without making real network requests.
Installing
Start by installing the @graphql-mesh/plugin-mock package:
npm i @graphql-mesh/plugin-mockHow to use?
Add it to your plugins:
import { defineConfig } from "@graphql-hive/gateway";
import { useMock } from "@graphql-mesh/plugin-mock";
export const gatewayConfig = defineConfig({
plugins: [
useMock({
mocks: [
{
apply: "User.firstName",
faker: "{{name.firstName}}",
},
],
}),
],
});The example above will replace the resolver of User.firstName with a mock that uses
faker.js to generate a random name.
Custom mock functions for fields
You can also provide a custom function to generate the mock value for a field:
import { defineConfig } from "@graphql-hive/gateway";
import { useMock } from "@graphql-mesh/plugin-mock";
import { fullName } from "./user-mocks.js";
export const gatewayConfig = defineConfig({
plugins: (pluginCtx) => [
useMock({
mocks: [
{
apply: "User.fullName",
custom: fullName,
},
],
}),
],
});Custom mock functions for types
You can mock types with custom mock functions like below;
import { defineConfig } from "@graphql-hive/gateway";
import { useMock } from "@graphql-mesh/plugin-mock";
import { user } from "./user-mocks.js";
export const gatewayConfig = defineConfig({
plugins: (pluginCtx) => [
useMock({
mocks: [
{
apply: "User",
custom: user,
},
],
}),
],
});export const mockFullName = () => {
return `John Doe`;
};When defined manually, properties can return values either directly or through a method. This is useful when defining static mocks because a mock property will be called as many times as there are items in an array. Here’s an example on how this could be achieved:
function* generateNames() {
while (true) {
yield "John Doe";
yield "John Snow";
}
}
const fullNames = generateNames();
export const fullName = () => fullNames.next().value;Mocking the lists
Hive Gateway generates two mocked items by default if the return type is a list. But this can be configured, as shown below:
type Query {
users: [User]
}
type User {
id: ID
fullName: String
}import { defineConfig } from "@graphql-hive/gateway";
import { useMock } from "@graphql-mesh/plugin-mock";
export const gatewayConfig = defineConfig({
plugins: (pluginCtx) => [
useMock({
mocks: [
{
apply: "User.fullName",
faker: "{{name.fullName}}",
},
{
apply: "Query.users",
length: 3,
},
],
}),
],
});Now query { users { id fullName } }{:graphql} query will return 3 of User item;
{
"users": [
{ "id": "SOME_RANDOM_ID", "fullName": "John Doe" },
{ "id": "SOME_RANDOM_ID", "fullName": "Jane Doe" },
{ "id": "SOME_RANDOM_ID", "fullName": "The Other Doe" }
]
}Stateful mocking
Hive Gateway supports GraphQL Tools' Stateful Mocking feature. So you can have stateful mocking by
using the store provided in the context context.mockStore;
Initialize store
When having a schema that returns a list, in this case, a list of users:
import type { IMockStore } from "@graphql-mesh/plugin-mock";
export function initializeStore(mockStore: IMockStore) {
const users = [{ id: "uuid", name: "John Snow" }];
// Set individual users' data in the store so that they can be queried as individuals later on
users.forEach((user) => {
mockStore.set("User", user.id, user);
});
// Populate the `users` query on the root with data
mockStore.set("Query", "ROOT", "users", users);
}Get from the store
You can implement the mock query field *ById declaratively like below:
type Query {
user(id: ID): User
users: [User]
}import { defineConfig } from "@graphql-hive/gateway";
import { useMock } from "@graphql-mesh/plugin-mock";
import { initializeStore } from "./init-store.js";
export const gatewayConfig = defineConfig({
plugins: (pluginCtx) => [
useMock({
initializeStore,
mocks: [
{
apply: "Query.user",
custom: (_, args, context) => context.mockStore.get("User", args.id),
},
],
}),
],
});Mutate data in the store
type User {
id: ID
name: String
}
type Query {
me: User
user(id: ID): User
users: [User]
}
type Mutation {
changeMyName(newName: String): User
updateUser(id: ID, name: String): User
}import { defineConfig } from "@graphql-hive/gateway";
import { useMock } from "@graphql-mesh/plugin-mock";
import { initializeStore } from "./init-store.js";
interface User {
id: string;
name: string;
}
export const gatewayConfig = defineConfig({
plugins: (pluginCtx) => [
useMock({
initializeStore,
mocks: [
{
apply: "Query.me",
custom: (_, args, context) => context.mockStore.get("User", "uuid"),
},
{
apply: "Mutation.changeMyName",
custom: (_, args, context) => {
const user = context.mockStore.get("User", "uuid") as User;
user.name = args.newName;
context.mockStore.set("User", "uuid", user);
return user;
},
},
{
apply: "Mutation.updateUser",
custom: (_, args, context) => {
const user = context.mockStore.get("User", args.id) as User;
user.name = args.name;
context.mockStore.set("User", args.id, user);
return user;
},
},
],
}),
],
});