Today’s web apps rarely live alone. They often make requests to external APIs via HTTP requests.
Fortunately, testing these kinds of code isn’t too hard since we can mock the HTTP responses. This means that our tests don’t have to make the requests in our tests, which is critical for writing repeatable and independent tests.
In this piece, we’ll look at how to test an Express app that interacts with an external API.
Creating a Simple App
First, we create the app that we’ll test. The app will get a random joke from the Chuck Norris Jokes API.
Next, we create an empty project folder and run:
npm init -y
To create an empty
package.json file with the default answers.
Next, we install Express and Node-Fetch to create the app and get data from APIs, respectively.
npm i express node-fetch
To install the packages.
Then we create
app.js and add:
To make the app that gets the joke and returns it as the response.
Adding the Test
To add the test, we use the Jest test runner to run the test and check the results, Nock to mock the response for the request that we made in
app.js, and Supertest to run the Express app and get the response that we can check.
To do this, we run:
npm i nock supertest jest
Then we create
app.test.js for the test code and then add:
In the file.
The code above starts by including our app from
app.js and the libraries we use for building the test.
const app = require('./app'); const nock = require('nock'); const request = require('supertest');
The first line above imports the Express app instance from
app.js. Then the other two lines import the Nock and Supertest libraries, respectively.
Then we add the skeleton for the test by calling
test from Jest and pass in the description and
async function since we’ll use the promise version of Supertest.
Then using Nock, we mock the response as follows:
As we can see, the mock request is a GET request, which is the same as what we had in
app.js. Also, the URL is the same as what we had there.
The difference is that we return a 200 response with the
mockResponse object in the test.
Now it doesn’t matter what the actual API returns. Nock will intercept the request and always return the content of
mockResponse as the response body for the request made in our route in
Then we just have to call the route with Supertest as follows:
const res = await request(app).get('/');
To call the route in
app.js and then check the response as follows:
toEqual method checks for deep equality so we can pass in the whole object to check.
Running the Test
Now to run our test, we have to add:
"test": "jest --forceExit"
scripts section of
We need the
--forceExit option so that the test will exit once the test is run. This is a bug that’s yet to be resolved.
Now we can run the test by running:
Then we should get:
We should get the same thing no matter how many times we run the test since we mocked the response of the API.
The real API returns something different every time we make a request to it, so we can’t use it for our tests.
Even if we could, it’d be much slower and the API might not always be available.
With Nock, we can mock responses easily for external API requests in our app. Then we can focus on just running our app’s code and checking the results.
Now we have tests that run fast and produce repeatable results that don’t depend on anything external to the tests.