reactjsmockingapollo-clientgraphql-toolsapollo-link

Using graphql-tools, apollo-link-schema, and react-hooks always returning undefined when mocking


I'm new to using GraphQL in React and have been moving a project from a REST API to a new GraphQL one. As part of this, I wanted to setup mock data to work on the application independent of the GQL API being completed. I've spent a bunch of time trying to follow the Apollo and GraphQL Tools docs but no matter what, I can't seem to get the mock resolvers to work properly. For context, I am using this in a NextJS/React app, and here's a minimum example of what I'm trying to do:

Setup App.js

import React from 'react';
import ApolloClient from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
import { SchemaLink } from 'apollo-link-schema';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { addMocksToSchema } from '@graphql-tools/mock';

export default function App() {
    const schema = makeExecutableSchema({typeDefs:`
        type Query {
            getPerson: Person!
        }
                
        type Person {
            name: String!
        }
    `});

    const mocks = {
        Query: () => ({
            getPerson: () => ({
                name: () => "Name"
            })
        })
    }

    addMocksToSchema({ mocks, schema });
    const link = new SchemaLink({ schema });
    const client = new ApolloClient({
        link,
        cache: new InMemoryCache(),
        connectToDevTools: true
    });

    return (
        <ApolloProvider client={client}>
            <Person />
        </ApolloProvider>
    )
}

Person.js

import React from 'react';
import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';

export default function Person() {
    const { loading, error, data } = useQuery(gql`
        query PersonQuery {
            getPerson {
                name
            }
        }
    `, {
        errorPolicy: 'all'
    });

    console.log(data);

    if (loading) return "Loading...";
    if (error) console.log(error);

    return (
        <h1>{data.getPerson.name}<h1>
    )
}

Looking at the console.log(error) result yields the error Cannot return null for non-nullable field Query.getPerson and making it a nullable field just returns { getPerson: null } of course. I've tried returning the resolver results as objects vs functions. Logging within the resolvers shows the Query part is being executed but nothing nested within that.

Am I setting something up incorrectly? I also tried not passing in custom mocks as suggested should be possible based on the graphql-tools docs, but to no avail. I also saw this issue from the apollo hooks GitHub that said the newest version of hooks broke the usage of addMocksToSchema, so I tried using the suggested 3.1.3 version but again no luck. Any help would be greatly appreciated!


Solution

  • You need to provide the mock to the client, not the plain schema.

    const schemaWithMocks = addMocksToSchema({
      schema,
      mocks: {},
      preserveResolvers: false,
    });
    
    const client = new ApolloClient({
      // link: new SchemaLink({ schema }); < -- REPLACE THIS
      link: (new SchemaLink({ schema: schemaWithMocks }) as unknown) as ApolloLink, // https://github.com/apollographql/apollo-link/issues/1258
      cache: new InMemoryCache(),
      connectToDevTools: true,
    });
    

    Now console.log(data) prints {"getPerson": {"__typename": "Person", "name": "Name"}} 🎉