Introduction
This tutorial will guide you through creating a GraphQL mock server for your JavaScript application. A mock server is invaluable for local development, enabling seamless testing when the backend is unavailable or while running E2E tests.
Prerequisites
Before proceeding, ensure the following tools are installed on your system:
- Node.js
- npm/yarn/pnpm
Step-by-step Guide
1. Install Dependencies
Begin by installing the necessary dependencies with npm or yarn:
npm install --save-dev graphql graphql-tag graphql-tools @apollo/server node-fetch
2. Setup Project Structure
Set up your project directory as follows:
/graphql-mock-server
|-- localSchema.ts
|-- schema.graphql
|-- server.ts
3. Local Schema
Define your local schema in localSchema.ts. This schema will override remote schema definitions for specific queries or mutations. Provide resolvers to return predefined mock data.
// filepath: /graphql-mock-server/localSchema.ts
import { makeExecutableSchema } from '@graphql-tool/schema'
import { gql } from 'graphql-tag'
const typeDefs = gql`
type Query {
myQuery: String
}
`;
const resolvers = {
Query: {
myQuery: () => 'This is mock data'
},
};
export const localSchema = makeExecutableSchema({typeDefs, resolvers});
4. Remote Schema
The remote schema is loaded from the local file schema.graphql
. This file should include the schema definition, which can be exported from your GraphQL playground.
// filepath: /graphql-mock-server/schema.graphql
type Query {
myQuery: String
}
5. Mock Server Implementation
The mock server stitches the local and remote schemas, giving precedence to the local schema-specified queries or mutations.
// filepath: /graphql-mock-server/server.ts
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import { stitchSchema } from '@graphql-tools/stitch';
import { loadSchemaSync } from '@graphql-tools/load';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { localSchema } from './localSchema';
import { wrapSchema } from '@graphql-tools/wrap';
import { print } from 'graphql';
import fetch from 'node-fetch';
async function startServer(){
const remoteSchema = loadSchemaSync('graphql-mock-server/schema.graphql',{
loaders: [new GraphQLFileLoader()],
});
const executableRemoteSchema = wrapSchema({
schema: remoteSchema,
executor: async ({ document, variables }) => {
const query = print(document);
const fetchResult = await fetch(
'https://graphql.server.com/graphql',
{
method: 'POST',
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({ query, variables}),
},
);
return fetchResult.json();
},
});
const schema = stitchSchema ({
subschema: [
{ schema: executableRemoteSchema },
{ schema: localSchema },
merge: {
myQuery: { //override the Query/Mutation here
selectionSet: '{ __typename }',
resolve: (parent, args, context, info) => {
return localSchema
.getQueryType()
?.getFields()
.myQuery.resolve(parent, args, context, info);
},
},
},
},
},
],
});
const server = ApolloServer({ schema });
const {url } = await startStandaloneServer( server, {
listen: { port: 4000},
});
console.log(`π Server ready at ${url}`);
}
startServer();
If you have reached here, then I made a satisfactory effort to keep you reading. Please be kind enough to leave any comments or share corrections.
Top comments (0)