The Big Mac index is a purchasing power parity index published by The Economist. Jest fetch testing is a tech task so frustrating that it almost made me quit the industry.
Screenshots don’t have gifs, here:
I’m writing this so you don’t have to read 8234721 different blog posts, stack overflow answers, and GitHub threads with conflicting info on how to get Jest and fetch to play together.
Library where I got it working 👉 bigmac-index-price-calculator.
Context is a project built from scratch without a CLI generator. Maybe that was part of my pain.
How to test fetch requests with Jest
A couple of ground rules:
- Our test suite must work offline. You shouldn’t be blocked from coding just because you’re on an airplane even if coding on an airplane is a terrible idea and you should really get some sleep instead.
- Our test suite must be reliable. You don’t want to get different results running at different times. No expiring API keys, no changing responses, no network failures.
Jest tests run in node. Node doesn’t have fetch. You have to use a library for that too. There’s a fetch polyfills and ponyfills and Idontknowwhatelsefills out there. I found at least 3.
isomorphic-fetch is the library I got working in the end.
Let us begin.
Assuming you’ve got an empty project initialized with
npm init or
yarn init, you start by installing everything you’ll need
Dev dependencies are those only used in development. We need Jest itself, its type definitions, its TypeScript sister, and fetch-mock.
ts-jest gives you TypeScript testing superpowers so you don’t have to compile your code first and test second. Test your TypeScript directly. It’s nice.
isomorphic-fetch both in development and when running live. That way your library doesn’t break if used server-side in Gatsby or something.
Configure Jest in a
jest.config.js file. There’s a bunch of info out there on where exactly this configuration should live. This is the one that finally worked for me.
We’re saying code lives in a
/src directory and that typescript files should run with
Mock fetch requests
Jest has built-in support for mocking entire libraries. That was a nice discovery after trying many approaches from many articles and tutorials.
You put files in a
__mocks__ directory and they overwrite the library you’re calling.
fetch-mock instead of
isomorphic-fetch in your tests, create a file like this:
This means that every time you import
isomorphic-fetch in a test file, it will instead import a sandboxed
fetch-mock instance. You can add any other setup you want here. Anything you need for your mocks to work correctly.
BIG WARNING 👉 you have to use the
import from to work, but I eventually gave up.
Write a Jest fetch test
We’re ready to write a test. Everything should work.
The file I’m testing is called
index.ts so my test file is called
index.test.ts. Here’s an example:
We’re in Jest now so we can use modern imports.
Rest mocks before each test so there’s no overlap, then mock an API request with a matcher and the response we want. The matcher in my case is a URL string, the exact URL my code is going to call, and the response is a JSON object.
200 for success and body for the data.
Now when you call
fetch(URL) in the code, it won’t make an API call, it’s just gonna get this response object.
Makes your tests fast, offline, and reliable. ✌️
The Big Mac purchasing parity code we’re testing
TDD says to write your test first and your code second, but I actually wrote the code first. Here’s the part we’re testing above 🙂
ParityPrice with your Ipstack API key (you can get one for free) and call
.price() with the price you’re trying to parity match.
bigmac-index-price-calculator then calls Ipstack to geolocate your visitor based on IP, looks up their country in the BigMacIndex and returns the adjusted price.
The full version has some continent-based conversions when a country isn’t found and a bit of caching so you can call multiple times without making too many requests. It works pretty well.
RIDICULOUS WARNING 👉 notice the
const fetch = require() part up top? That’s because while modern imports work for Jest files and they definitely work when packaging your library, I couldn’t get them to work when testing your library. I tried everything. Nothing worked.
Purchasing power parity on reactfordataviz.com
Don’t click the button yet though. I haven’t wired up the adjusted prices with Gumroad yet.
A lot of people have been asking for this and I think it’s a great idea. Value based pricing all the way. If learning React Dataviz gets you a $150,000/year job in USA that’s very different value than a $50,000/year job somewhere else.
Learned something new? Want to improve your skills?
Join over 10,000 engineers just like you already improving their skills!
Here's how it works 👇
PS: You should also follow me on twitter 👉 here.
It's where I go to shoot the shit about programming.