Testing GraphQL in 3 minutes

Cole Turner
Cole Turner
3 min read
Cole Turner
Testing GraphQL in 3 minutes

You look outside the window and see the clouds crawling on by while you take a sip of your morning coffee and ask yourself:

“How exactly do I test my GraphQL resolvers?”

I never said I was a mind reader. But for the folks out there that are wondering that very same question, here is how you should start testing your GraphQL Server.

The first thing you want to cover is schema composition. Mocking your schema lets you write tests with real queries that test your type definitions. These tests will save you from a magnitude of potential glitches including typos and type conflicts.

Mock the schema and write test cases for every query you can imagine. Add cases for happy paths, errors, and test different contexts as well. Declaring these concerns gives us the full integration testing our Schema needs and peace of mind. Here’s how I like to do it:

import {
} from 'graphql-tools';

const testCaseA = {
  id: 'Test case A',
  query: `
    query {
      animals {
  variables: { },
  context: { },
  expected: { data: { animals: [{ kind: 'Dog' }] } }

describe('Schema', () => {
  // Array of case types
  const cases = [testCaseA];
  const mockSchema = makeExecutableSchema({ typeDefs });

  // Here we specify the return payloads of mocked types
    schema: mockSchema,
    mocks: {
      Boolean: () => false,
      ID: () => '1',
      Int: () => 1,
      Float: () => 12.34,
      String: () => 'Dog',

  test('has valid type definitions', async () => {
    expect(async () => {
      const MockServer = mockServer(typeDefs);

      await MockServer.query(`{ __schema { types { name } } }`);

  cases.forEach(obj => {
    const { id, query, variables, context: ctx, expected } = obj;

    test(`query: ${id}`, async () => {
      return await expect(
        graphql(mockSchema, query, null, { ctx }, variables)


In the example above we iterate through the test cases using the declared fixtures. These fixtures contain the query that will execute against our mock schema. We can specify variables, context, and the expected output from the query. This gives developers peace of mind that GraphQL can make an executable schema out of type definitions. But what about resolvers? What about integration testing beyond GraphQL?

The really neat thing about resolvers is that they’re pure functions — which makes writing tests super easy and satisfying. For a refresh, here’s what a resolver function looks like:

function animalNameResolver(obj, args, ctx, info) {
  // obj     = the parent object (Animal)
  // args    = the query field arguments
  // ctx    = shared payload for query execution
  // info    = query and field selection metadata
  return obj.name;

Pure functions are great for testing because there’s no internal state and no mutable payloads to worry about. Mocking the shape of these arguments we can test resolvers and add integration coverage to our test suites. This way we know our schema is valid and integrates with underlying services.

Here’s something simple to get started:

// graphql/types/Animal/Animal.test.js
import * as AnimalResolvers from './Animal.resolvers.js';

export const animalNameTest = () => {
    const obj = {
      kind: 'Dog',
      name: 'Koko',
      breeds: ['Corgi', 'German Shepherd']
    const args = {};
    const ctx = {};

    const output = AnimalResolvers.name(obj, args, ctx);

// graphql/types/resolvers.test.js

import glob from 'glob';
import path from 'path';

const basePath = path.join(process.cwd(), './graphql/types/');

describe('Resolvers', () => {
  // Find all our resolver files
  const files = glob.sync(`${basePath}**/*.test.js`);
  files.forEach(file => {
    describe(file, () => {
      const resolvers = require(file);

      Object.entries(resolvers).forEach(([name, fn]) => {
        it(name, () => Promise.resolve(fn()));

I like this pattern because I’ve found co-locating tests with your Schema to be just as advantageous to putting tests next to React components. It makes it easier to remember to write tests and helps the next developer gather the big picture. Friction when writing tests is the worst productivity killer at the cost of the testing coverage. Making tests easier to write is a no-brainer.

GraphQL Test Result - Tests Pass

Thanks for reading! GraphQL and Apollo are awesome frameworks that make building a schema in JavaScript a pleasure. If you find some other pattern that does the same for you — please feel free to share.


More Stories

Why I Don't Like Take-Home Challenges

4 min read

If you want to work in tech, there's a chance you will encounter a take-home challenge at some point in your career. A take-home challenge is a project that you will build in your free time. In this post, I explain why I don't like take-home challenges.

Standing Out LOUDER in the Technical Interview

5 min read

If you want to stand out in the technical interview, you need to demonstrate not only your technical skills but also your communication and collaboration skills. You need to think LOUDER.

See more posts

Read it before anyone else. Subscribe to my newsletter for early access to the latest news in software engineering, web development, and more.