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.
How to use?
npm install @graphql-mesh/plugin-mock
Then, add it to your plugins:
import useMock from '@graphql-mesh/plugin-mock'
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
export const serveConfig = defineServeConfig({
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 as defineServeConfig } from '@graphql-mesh/serve-cli'
import { fullName } from './user-mocks.js'
export const serveConfig = defineServeConfig({
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 as defineServeConfig } from '@graphql-mesh/serve-cli'
import { user } from './user-mocks.js'
export const serveConfig = defineServeConfig({
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
Mesh 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 useMock from '@graphql-mesh/plugin-mock'
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
export const serveConfig = defineServeConfig({
plugins: pluginCtx => [
useMock({
mocks: [
{
apply: 'User.fullName',
faker: '{{name.fullName}}'
},
{
apply: 'Query.users',
length: 3
}
]
})
]
})
Now query { users { id fullName } }
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
GraphQL Mesh 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 { MockStore } from '@graphql-mesh/plugin-mock'
export const store = new MockStore()
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 => {
store.set('User', user.id, user)
})
// Populate the `users` query on the root with data
store.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
}
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
import { store } from './init-store.js'
export const serveConfig = defineServeConfig({
plugins: pluginCtx => [
useMock({
store,
mocks: [
{
apply: 'Query.user',
custom: (_, args) => store.get('User', args.id)
}
]
})
]
})
Mutate data in the store
type User {
id: ID
name: String
}
type Query {
me: User
}
type Mutation {
changeMyName(newName: String): User
updateUser(id: ID, name: String): User
}
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
import { store } from './init-store.js'
export const serveConfig = defineServeConfig({
plugins: pluginCtx => [
useMock({
store,
mocks: [
{
apply: 'Query.me',
custom: (_, args, context) => store.get('User', 'uuid')
},
{
apply: 'Mutation.changeMyName',
custom: (_, args, context) => {
const user = store.get('User', 'uuid')
user.name = args.newName
store.set('User', 'uuid', user)
return user
}
},
{
apply: 'Mutation.updateUser',
custom: (_, args, context) => {
const user = store.get('User', args.id)
user.name = args.name
store.set('User', args.id, user)
return user
}
}
]
})
]
})
TODO: Move example to here