Client-side query mocking with Apollo 2.0, react-apollo, and apollo-link-schema

I'd like to be able to mock out some queries on the client-side so I don't have to provide a GraphQL endpoint in order to work on my React app.

According to the Apollo docs, it looks like I should be using apollo-link-schema. I've tried to follow the example, but in my case I end up with an error: Network error: Expected undefined to be a GraphQL schema. when trying to access the query result inside my wrapped component.

Can someone help me understand what I'm doing wrong here?

Here's a fully contained index.js example to illustrate my problem:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

import { ApolloProvider } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import { SchemaLink } from "apollo-link-schema";
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloCache } from 'apollo-cache';

import gql from 'graphql-tag';
import { graphql } from 'react-apollo';

import { makeExecutableSchema, addMockFunctionsToSchema, MockList } from 'graphql-tools';
const typeDefs = `
type Query {
  me: Person!
}

type Person {
    name: String!
}
`;
const schema = makeExecutableSchema({ typeDefs });
addMockFunctionsToSchema({ schema });

const schemaLink = new SchemaLink(schema);
const client = new ApolloClient({
    link: schemaLink,
    cache: new InMemoryCache()
});

class App extends Component {
  render() {
        if (this.props.query && this.props.query.loading) {
            return <div>Loading...</div>
        }

        if (this.props.query && this.props.query.error) {
            return <div>Error: {this.props.query.error.message}</div>
        }

        const person = this.props.query.me;
        return <div> {person.name} </div>
  }
}

const personQuery = gql`
    query PersonQuery {
        me {
            name
        }
    }
`;
App = graphql(personQuery, { name: 'query' })(App);

ReactDOM.render(
    <ApolloProvider client={client}>
        < App />
    </ApolloProvider>
    , document.getElementById('root')
);

1 answer

  • answered 2018-02-13 03:49 Gabe Hollombe

    Update: I can get things working using MockedProvider from react-apollo/test-utils but I'm wondering if this is the best way forward. For example, as far as I can tell using MockedProvider requires that you set up exact matches for each query your component might perform, whereas addMockFunctionsToSchema from graphql-tools will let you customize your mocks more flexibly, as indicated in the docs -- I just wish I could make that work.

    Here's the updated index.js file example working with MockedProvider:

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    
    import { ApolloProvider } from 'react-apollo';
    import { ApolloClient } from 'apollo-client';
    import { SchemaLink } from "apollo-link-schema";
    import { InMemoryCache } from 'apollo-cache-inmemory';
    import { ApolloCache } from 'apollo-cache';
    
    import gql from 'graphql-tag';
    import { graphql } from 'react-apollo';
    
    import { MockedProvider } from 'react-apollo/test-utils';
    
    import { makeExecutableSchema, addMockFunctionsToSchema, MockList } from 'graphql-tools';
    const typeDefs = `
    type Query {
      me: Person!
    }
    
    type Person {
        name: String!
    }
    `;
    const schema = makeExecutableSchema({ typeDefs });
    addMockFunctionsToSchema({ schema });
    
    const schemaLink = new SchemaLink(schema);
    const client = new ApolloClient({
        link: schemaLink,
        cache: new InMemoryCache()
    });
    
    class App extends Component {
      render() {
            if (this.props.query && this.props.query.loading) {
                return <div>Loading...</div>
            }
    
            if (this.props.query && this.props.query.error) {
                return <div>Error: {this.props.query.error.message}</div>
            }
    
            const person = this.props.query.me;
            return <div> {person.name} </div>
      }
    }
    
    const personQuery = gql`
        query PersonQuery {
            me {
                __typename
                name
            }
        }
    `;
    const personQueryMockedData = {
        me: {
            __typename: 'String',
            name: 'Gabe'
        }
    }
    
    
    App = graphql(personQuery, { name: 'query' })(App);
    
    ReactDOM.render(
        <MockedProvider mocks={
            [
                { 
                    request: { query: personQuery, variables: { cache: false } },
                    result: { data: personQueryMockedData }
                }
            ]
        }>
            < App />
        </MockedProvider>
        , document.getElementById('root')
    );