Testing your Apollo Links
Tags: javascript, graphql, apollo, apolloclient
Published: 2020-07-07 17:55:51

---
title: Testing your Apollo Links
published: true
description: Testing is important. You should do it. This article showcases how you might test your Apollo Links.
tags: javascript, GraphQL, Apollo, ApolloClient
cover_image: https://www.freecodecamp.org/news/content/images/size/w2000/2020/04/cover-3.png
---

# Testing your Apollo Links

If you are using _Apollo Client_ you are using _Apollo Links_.
These powerful pieces of _middleware_ / _afterware_ allow you to augment requests in variety of ways or help with [authentication](https://www.apollographql.com/docs/react/networking/authentication/).

While using _Apollo Links_ is great, we as a responsible software developers should write tests for various pieces of our application to make sure everything is working as intended.
This rule also applies to _Apollo Links_.

In this article I'm going to go through testing basic [authentication link](https://www.apollographql.com/docs/react/v3.0-beta/networking/advanced-http-networking/#customizing-request-logic) to show you how I'm maintaining confidence in this part of the application I'm working on.

_Please note that the references are based on Apollo 3.0 documentation. While there are many changes between versions 2.x and 3.x the ideas and APIs that will be used in this article are the same_.

## Basic `authLink`

We are going to follow [official Apollo docs](https://www.apollographql.com/docs/react/v3.0-beta/get-started/) and start with the basic `localStorage` based authentication link.

Here is the code:

```js
import { ApolloLink } from "@apollo/client";

const authLink = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: {
      Authorization: localStorage.getItem("token")
    }
  });

  return forward(operation);
});
```

Nothing fancy here, we are retrieving the token from the `localStore` and setting the `Authorization` header using the `setContext` API which is made to resemble the `setState` API from _React_ class components.

The function that I passed to `ApolloLink` is the middleware itself. I'm using `forward` to pass the control of the execution to the next link in the chain.

Now let's get going with the tests.

## Setup for the tests

First of all we have to have a way to actually invoke our link, otherwise we will not be able to set the `Authorization` header value.

Luckily, there is one utility which _Apollo Client_ exposes that can help us with that, mainly a function called `execute`. This function allows us to execute `GraphQL` request and pass a link(s) which will be invoked during that execution.

Let's create a simple utility function which uses `execute` to trigger the link chain during the request.

```js
import { execute, gql } from "@apollo/client";

const MockQuery = gql`
  query {
    foo
  }
`;

function executeRequest(link) {
  execute(link, { query: MockQuery }).subscribe(() => {
    /* not our concern within this test */
  });
}
```

The `query` itself does not matter, it is only there to trigger a request.
I've also had to `subscribe` to the `execute` function. This part is really an implementation detail that you should not concern yourself with.

_For the curious minds out there, Apollo uses `Observables` underneath. These are lazy by default so to trigger `MockQuery` we had to use the `subscribe` function_.

Next step is to create another link which will be used for making assertions.
Since this will be the last link of the chain, it has to be a [terminating link](https://www.apollographql.com/docs/link/overview/#terminating-links). This just means that we will not use `forward(operation)` but return `null` instead.

```js
const assertLink = new ApolloLink(operation => {
  const headers = operation.getContext().headers;
  // we will make assertions here.
  return null;
});
```

All we are doing here is getting the `headers` from the `context` and potentially making assertions on the `headers` object.

## The actual test

With every piece of the puzzle ready to be put together, let's write a test case which will make sure that the `authLink` actually sets the `Authorization` header.

```js
function executeRequest(link) {
  // previous implementation
}

// const authLink = ... previous implementation

it("sets the `Authorization` header to the correct value", () => {
  // remember to reset the value in-between tests!
  localStorage.setItem("token", "token");

  const lastLink = new ApolloLink(operation => {
    const headers = operation.getContext().headers;
    expect(headers.Authorization).toEqual("token");

    return null;
  });

  // compose our links together
  // .concat API might be an alternative, but I will stick with `.from` here.
  const link = ApolloLink.from([authLink, lastLink]);

  executeRequest(link);
});
```

The test itself is not very sophisticated and it should not be.
All we are doing here is a simple assertion which gives us **some** confidence in how our `authLink` is working.

While this is only one test case, in my opinion, it showcases the steps that you can take to test **any** kind of link that you might use.

Another thing to think about is how we could refresh this `token`. We might be dealing with `accessToken` and `refreshToken` within our apps after all. Well, for that, stay tuned for my next article :)

## Summary

I hope that with this article I was able to give you some insight on how you **might** test your custom _Apollo Links_. I'm using this technique for some time now and it's been working great, even for a bit more complicated links.

If you want to read more about testing itself, my colleagues have written some great articles in the past:

- [Jędrzej wrote about the challenges you might face while writing tests](https://dev.to/jbszczepaniak/why-don-t-you-test-the-way-you-d-like-to-25f7)

* [Tomasz wrote about the importance of testing](https://dev.to/tlakomy/why-frontend-testing-matters-34jn)

- And if you are into Go just like I am, there is [this great article](https://dev.to/prozz/serverless-in-go-how-to-write-testable-lambdas-4925) about testing lambdas written in Go.

Thanks 👋