Learning to test React Native with Jest — part 4

Mocking API calls; odds and ends

Jason Gaare
React Native Training
4 min readJun 29, 2017

--

Previously, we’ve looked at testing elements that interact with other elements within our app. In this article, we’ll learn how to mock API calls and simulate the way our React Native application handles making external requests.

Mocking API calls

Note: There are plenty of choices for a HTTP client in React Native, including the built in Fetch API detailed in the networking docs. In our application, we utilize Axios for our HTTP client to interact with our API, so for the purposes of this tutorial that will be the client of choice. If you utilize the Fetch API, check out this article and this article to get started.

Getting things set up

To test calls to our API, we’ll want to essentially intercept and mock our requests, to control the responses. Using Axios as our client, we’ll want to mock the way that library works. Fortunately, there is a library to help us do that, so our first step is to install axios-mock-adapter.

Next, we set up our mock as follows:

What’s happening here:

  1. We pull in our apiClient from the helper we’ve written internally and pass the Axios instance into the mock adapter (line 5). Your set up might be slightly different, but the key is to pass an instance of Axios into the mock adapter.
  2. Next we set up a mock reply for when the POST method that hits api.url/sessions is called.
  3. Inside our reply, we conditionally return either a success or failure depending if our input matches the validAuth that we define above. The success returns a userObject that has the same format as the object returned from our API.

Writing our test

Now that we have our mocks all set up, let’s write up our test! And we’ll be using— you guessed it — snapshots!

Unpacking our tests

You might recognize this test from part 3; we’ve already seen how to utilize getActions() from our mock store and create a snapshot.

Last time though, I failed to mention the importance of the use of async and await. If we do not use these, our expect statement is called before our dispatched action completes — and store.getActions is empty. Not a very good test! Thus, we need to use await on our dispatched action before we create our snapshot.

If you look at our test for a failed authentication, the expect statement is in our catch block since our dispatched action returns a rejected promise. Also, we deleted the duration value on our error object. The duration varies slightly whenever we run our test (usually either zero or one second). This is an accepted variable, so we just delete it.

New! Jest 20 adds .resolves and .rejects to make handling promises even easier. Check it out in the documentation here.

That’s it!

It’s rather straight forward to mock HTTP requests for our API client. We can create a conditional controlled response to ensure our code handles every response from our requests. Simply confirm your snapshots look as expected, and we’re done! Check out the complete test code here.

Odds and Ends

These are just a few one-off topics I wanted to throw your way as I wrap up this series.

Jest CLI

I’ve only mentioned utilizing npm test to run our tests, but there’s also the Jest CLI you can use. You’ll need to install it globally: npm i -g jest-cli. This tool is especially helpful to run individual tests, rather than your entire test suite. Checkout the docs here.

Writing your own mocks

Writing mocks allows you to test your code without worrying about code from another library. I like to mock on an as-needed basis, that way I don’t have any extraneous mocks laying around. Here’s a quick example of a simple mock for the Animated library from React Native, which only mocks the functionality we needed:

Mocks can either be placed in a setup file referenced from your Jest configuration, or in a file in a __mocks__ folder.

You should definitely checkout react-native-mock for inspiration (or for utilization!) I haven’t used the library yet, but am frequently visiting the code to see how they mock things.

Be careful of automock

I’ve seen a handful of tutorials that recommend turning automock on to avoid errors when running tests. This can be handy, but also can cause performance issues, especially in larger projects. Further, if you have the patience, I find it valuable to know what I am mocking. Manually mocking allows me to control exactly what my tests will receive from mocked libraries.

Coverage Reports

When running code coverage here are a few tips:

  1. 100% coverage isn’t necessarily 100% coverage. As we saw in part 2, just because a line is covered doesn’t mean we’ve actually tested its functionality.
  2. Utilize configuration options. Check the Jest configuration docs for all the details, but you should be selective about where you collect coverage from to get the most accurate reports.
  3. Browse the report via HTML. By default, a folder conveniently named “coverage” is created when you run --coverage (tip: put this folder in your .gitignore). Open coverage/lcov-report/index.html in your web browser, you’ll find an easily navigable interface to dive into folders and files and determine where you are missing coverage.

The end is here.

This is the conclusion of this series on how I learned to test React Native using Jest. I do hope it’s been helpful. If there’s anything else you’d like covered please respond below, and you never know maybe there might just be an epilogue…

More in this series

Part 1Part 2Part 3

--

--

Jason Gaare
React Native Training

Mobile developer at @CompanyCam. Husband, father, follower of Christ.