Mocking in Angular: Faking a GraphQL backend

GraphQL cube

When you think about mocks, the first thing that comes to mind is testing. Mock your dependencies, mock your services, mock your components — so that you can just test in isolation.

Mock - word definition

As per Austin’s amazing article on mocking — there’s more to it than just tests.

In this post, we will focus on how we can mock a GraphQL backend. This is useful if you’re a Frontend developer, and GraphQL is maintained by a separate team. This means that writing GraphQL mocks directly using something like GraphQL Faker isn’t really an option.

If you’re already using GraphQL and Apollo in your project, chances are you already have all the dependencies needed installed. In this case, it would take just a few minutes to set the whole thing up. If you’re just getting started, all you would need in order to hook it up are the following commands:

npm i graphql
npm i apollo-angular
npm i apollo-angular-link-http
npm i apollo-cache-inmemory
npm i apollo-client
npm i apollo-link
npm i apollo-link-http
npm i graphql-tag

Now that we have everything we need, let’s dig into the interesting part: intercepting GQL requests.

To avoid forwarding the operation to the ApolloClient, we would want to create our own ApolloLinks that would give us total control over outgoing requests.

This is very easy to achieve by adding a MockLinkProvider. An alternative would be to use the MockLink.

Sidenote: You don’t want to push mock data to production. We will cover how to exclude these completely from the build in a future post.

  providers: [
      provide: MockLinkProvider, 
      useFactory: () => 
      new ApolloLink(
        (operation: Operation, forward: any) => handleOperation(operation, forward)
      provide: APOLLO_OPTIONS,
      useFactory: apolloProviders,
      deps: [MockLinkProvider]
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]

Once we have added our MockLinkProvider, we’re ready to handle all incoming operations. If you already have your mock data ready, you can go ahead and return it in the handleOperation function. You just need to make sure that you’re returning it as an Observable. It would look something like this:

import { Observable, Operation, RequestHandler } from 'apollo-link';
import { ExecutionResult } from 'apollo-link/lib/types';

export const handleOperation: RequestHandler = (operation: Operation, forward) =>
  Observable.of(mockData as ExecutionResult<typeof mockData>);

You can easily switch from mocks to no-mocks by adding a variable in your environment.ts file that would serve as a switch between the two modes. So, finally, you would have something like this:

import { Observable, Operation, RequestHandler } from 'apollo-link';
import { environment } from '../environments/environment';
import { ExecutionResult } from 'apollo-link/lib/types';

export const handleOperation: RequestHandler = (operation: Operation, forward) => {
  if (environment.useMocks) {
    let response = {} as any;

// Set response mock data...

return Observable.of(response as ExecutionResult<typeof response>);

} else {
    return forward(operation);

Last but not least, to use the custom MockLinkProvider, just include it in the APOLLO_OPTIONS provider dependencies as follows:

providers: [{
   provide: APOLLO_OPTIONS,
   useFactory: apolloProviders,
   deps: [MockLinkProvider]

And that’s pretty much it! You can see this in action in the example below:

angular-jzeugs — StackBlitz Starter project for Angular apps that exports to the Angular CLI

Published on Nov 20, 2019