April 11, 2016

Mocking your server with just one line of code

Jonas Helfer
Software Engineer
@helferjs
BackendHow-to

(Editor’s note — the concepts in this post are accurate, but some the code samples don’t demonstrate new usage patterns. After reading, consult the graphql-tools docs to see how to use mocking today.)

Do you think mocking your backend is always a tedious task? If you do, reading this article will probably change your mind…

Mocking is the practice of creating a fake version of a component, so that you can develop and test other parts of your application independently. Mocking your backend is a great way to quickly build a prototype of your frontend and lets you test your frontend without starting up any servers. API mocking is so useful that a quick Google search will turn up dozens of expensive products and services that promise to help you.

Sadly, I think none of the solutions out there makes it as easy as it should be. As it turns out, that’s because they’ve been trying to do it with the wrong technology!

Mocking your backend doesn’t have to be rocket science!

Last week on Building Apollo I wrote about the set of tools that will eventually make up Apollo Server. Mocking is the first thing we can demo, and I hope you’ll enjoy it!


Why mock?

Mocking the data a backend would return is very useful for two main reasons:

  1. It lets you start developing a frontend feature when you don’t have a working backend for it yet. This is critical for projects where the frontend and backend components are often developed in parallel.
  2. It lets you run tests locally without connecting to a real backend, which is much faster and safer. As your codebase grows and your app becomes more complex, starting up all of the server infrastructure just to run some tests isn’t feasible.

If mocking your backend API has such clear benefits, why doesn’t everyone do it? I think it often seems like too much trouble to be worth it.

Why is mocking backends hard?

Let’s say your backend is some REST API that is called over http from the browser. You have someone working on the backend, and someone else working on the frontend. The backend code actually determines the shape of the data returned for each REST endpoint, but mocking has to be done in the frontend code. That means the mocking code will break every time the backend changes, unless both are changed at the same time. What’s worse, if you’re doing your frontend testing against a mock backend that is not up to date with your backend, your tests may pass, but your code won’t work. Rather than having to keep more dependencies up to date, the easy option is to just not mock the REST API, or have the backend be in charge of mocking itself, just so it’s all in one place. That may be easier, but it will also slow you down.

The other reason I often hear for why people don’t mock the backend in their project is because it takes time to set up: first you have to include extra logic in your data fetching layer that lets you turn mocking on and off, and second you have to actually describe what that mock data should like. For any non-trivial API that requires a lot of tedious work.

Both of these reasons for why mocking backends is hard are actually due to the same underlying reason: there is no standard REST API description in machine-consumable format and contains all the information necessary for mocking and can be used by both the backend and the frontend. There are some API description standards, like Swagger, but they don’t contain all of the information you need, are cumbersome to write and maintain. Unless you want to pay a lot of money for a service or a product — and maybe even then — mocking is a lot of work.

Actually, I should say mocking was a lot of work, because something is about to change the way with think of APIs. That something is called GraphQL.


Mocking is easy with a type system!

GraphQL makes mocking easy, because it makes you define a type system for your backend. That type system can be shared between your backend and your frontend, and it contains all the information necessary to make mocking incredibly fast and convenient. You literally have no more excuse not to use mocking in development or testing.

If you don’t know about GraphQL yet, I recommend that you first read an Intro to GraphQL, otherwise the rest of this post might seem a bit like magic.

Here’s how easy it is to start mocking your backend for any valid GraphQL query with one of the GraphQL-tools we’ve built for Apollo:

// > npm install graphql-tools
import { mockServer } from 'graphql-tools';
import schema from './mySchema.graphql';

const myMockServer = mockServer(schema);
myMockServer.query(`{
  allUsers: {
    id
    name
  }
}`);

// returns
// {
//   data: {
//     allUsers:[
//       { id: 'ee5ae76d-9b91-4270-a007-fad2054e2e75', name: 'lorem ipsum' },
//       { id: 'ca5c182b-99a8-4391-b4b4-4a20bd7cb13a', name: 'quis ut' }
//     ]
//   }
// }

Every GraphQL server needs a schema, so it’s not extra code you need to write just for mocking. And the query is the one your component uses for fetching data, so that’s also not code you write just for mocking. Not counting the import statement, it only took us one line of code to mock the entire backend!

Put that in contrast to most REST APIs out there, where mocking means parsing a URL and returning data in a custom shape for each endpoint. It takes dozens of lines to mock a single endpoint that returns some realistic-looking data. With GraphQL, the shape is encoded in the query, and together with the schema we have enough information to mock the server with a single line of code.

Did I mention that this one line is all you need to return mock data for any valid GraphQL query you could send? Not just some valid query, any valid query! Pretty cool, right?


Customizing mock data

In the example above, the mock server will return completely random IDs and strings every time you query it. When you’ve just started building your app and only want to see if your UI code actually displays something, that’s probably good enough, but as you start to fine-tune your layout, or want to use the mock server to test your component’s logic, you’ll probably need more realistic data.

Luckily, it barely takes any more effort, because customization of mock data is really where the Apollo mocking tool shines. You can customize virtually everything about the mock data that it returns. It lets you do all of the following and more:

// customize mocking per type (i.e. Integer, Float, String)
mockServer(schema, {
  Int: () => 6,
  Float: () => 22.1,
  String: () => 'Hello',
});

// customize mocking per field in the schema (i.e. for Person.name and Person.age)
mockServer(schema, {
  Person: () => ({
    name: casual.name,
    age: () => casual.integer(0,120),
  })
});

// mock lists of specific or random length( and lists of lists of lists …)
mockServer(schema, {
  Person: () => {
    // a list of length between 2 and 6
    friends: () => new MockList([2,6]),
    // a list of three lists of two items: [[1, 1], [2, 2], [3, 3]]
    listOfLists: () => new MockList(3, () => new MockList(2)),
  },
});

// customize mocking of a field or type based on the query arguments
mockServer(schema, {
  Person: () => {
    // the number of friends in the list now depends on numPages
    paginatedFriends: (o, { numPages }) => new MockList(numPages * PAGE_SIZE),
  },
});

// You can also disable mocking for specific fields, pass through to the backend, etc.

For each type and each field you can provide a function that will be called on to generate mock data. Mock functions on fields have precedence over mock functions on types, but they work together really nicely: The field mock functions only need to describe the properties of the objects that matter to them, type mock functions will fill in the rest.

The mock functions are actually just GraphQL resolve functions in disguise. What that means is that your mocking can do anything that you could do inside a GraphQL resolve function. If you wanted, you could write your entire backend with it. I’m not saying you should, but you could.

I think the real power of this tool is that while it allows almost arbitrarily complex customization, you can get started really quickly and increase the sophistication of your mocks in tiny steps whenever you need it. Each step is so simple that it will feel like a breeze.

But enough talking, here’s a complete example:

import { mockServer, MockList } from 'graphql-tools';
import casual from 'casual-browserify';

// The GraphQL schema. Described in more detail here: 
// https://medium.com/apollo-stack/the-apollo-server-bc68762e93b
const schema = `
  type User {
    id: ID!
    name: String
    lists: [List]
  }
  type List {
    id: ID!
    name: String
    owner: User
    incomplete_count: Int
    tasks(completed: Boolean): [Task]
  }
  type Task {
    id: ID!
    text: String
    completed: Boolean
    list: List
  }
  type RootQuery {
    user(id: ID): User
  }
  schema {
    query: RootQuery
  }
`;

// Mock functions are defined per type and return an
// object with some or all of the fields of that type.
// If a field on the object is a function, that function
// will be used to resolve the field if the query requests it.
const server = mockServer(schema, {
  RootQuery: () => ({
    user: (o, { id }) => ({ id }),
  }),
  List: () => ({
    name: () => casual.word,
    tasks: () => new MockList(4, (o, { completed }) => ({ completed })),
  }),
  Task: () => ({ text: casual.words(10) }),
  User: () => ({ name: casual.name }),
});

mockServer.query(`
query tasksForUser{
  user(id: 6) {
    id
    name
    lists {
      name
      completeTasks: tasks(completed: true) {
        completed
        text
      }
      incompleteTasks: tasks(completed: false) {
        completed
        text
      }
      anyTasks: tasks {
        completed
        text
      }
    }
  }
}`);

Live demo + try it yourself

To see the example in action and see what output it generates, head over to the live demo and click the “play” button a couple of times!

If you want to fiddle around with the example, you can do that — it’s all on GitHub: apollostack/mock-demo. If you’re curious about how it works or want to see what other tools we’re building for GraphQL, then head over to apollostack/graphql-tools.

Pretty cool, right? All of that becomes possible by using a type system. And that’s only just the beginning — we‘re working on bridging the gap between mocking and the real thing so that your mock server can gradually turn into your real server as you add more functionality to it.


If you’ve liked this post, you might also be interested in the other posts on Building Apollo, written by Sashko and myself. We’re publishing two posts every week, about the stuff we’re working on or thinking about.

Written by

Jonas Helfer

Follow

Stay in our orbit!

Become an Apollo insider and get first access to new features, best practices, and community events. Oh, and no junk mail. Ever.

Similar posts

June 17, 2020

Register Schema Changes Automatically with Schema Reporting

by Ran Magen

Company