Mastering API Testing with Supertest, Express.js, and Jest
Published: Oct 26, 2023
Last updated: Oct 26, 2023
Introduction
Supertest is a highly efficient and flexible testing library designed for testing HTTP assertions.
Working hand in hand with frameworks like Express.js, Supertest makes it easy to write assertions for your APIs, ensuring they respond as expected. Coupled with Jest, a delightful JavaScript Testing Framework with a focus on simplicity, you can ensure that your APIs are robust and reliable. In this tutorial, we will dive into setting up a simple Express.js application and write tests using Supertest and Jest.
In this blog post, we will set up a basic Express app and write tests using Supertest and Jest.
At first, the tests will be straight forward on validating the response status. Then, we will dive into asserting the response body and its values.
All code from today can be found remotely on this repo.
Setting Up The Repository
Before we dive into writing our application and tests, we need to set up our repository. Here are the steps to do that:
# Create a new directory for your project mkdir demo-express-jest-supertest cd demo-express-jest-supertest # Initialize a new Node.js project pnpm init # Install necessary dependencies pnpm i express pnpm i -D jest supertest
Once our repository is set up, we can start writing our application and tests.
Crafting The Demo Express App
Let's build a simple Express.js application to demonstrate how we can test it using Supertest and Jest.
Firstly, create a new file app.js
at the root of the project directory using touch app.js
and add the following:
// app.js // 1. Require express const express = require("express"); // 2. Create the new express app instance for our API const app = express(); // 3. Define the route for the GET /greet endpoint app.get("/greet", (req, res) => { const name = req.query.name || "World"; res.json({ message: `Hello, ${name}!` }); }); // 4. Export the app for testing later module.exports = app;
In the above code, we add the following:
- We require the
express
module. - We create a new instance of the Express app.
- We define a route for the
GET /greet
endpoint that returns a JSON response with amessage
property. - We export the app instance for testing later.
This will set up our baseline Express app, but it does not start the server. If we want to do that, we need to create a new file server.js
at the root of the project directory using touch server.js
and add the following:
// 1. Import our app from the app.js file const app = require("./app"); // 2. Start the server on port 3000 app.listen(3000, () => { console.log("Server is running on port 3000"); });
At this point, we could run our app using node server.js
on the terminal and test it using a tool like curl
or Postman.
To confirm, we can run curl http://localhost:3000/greet
on the terminal and get the following response:
curl http://localhost:3000/greet # {"message":"Hello, World!"}
Running curl http://localhost:3000/greet?name=John
on the terminal will return the following response:
curl http://localhost:3000/greet?name=John # {"message":"Hello, John!"}
At this point, we are ready to write our first tests. You can stop running the server in the first terminal using Ctrl + C
and move onto the next section.
Writing Tests with Supertest and Jest
Now that we have our Express app ready, it's time to write some tests to assert the response and value of the body.
First, create a new file app.test.js
at the root of the project directory using touch app.test.js
and add the following:
// app.test.js const request = require("supertest"); const app = require("./app"); describe("GET /greet", () => { it("should greet the world when no name is provided", async () => { const res = await request(app) .get("/greet") .expect("Content-Type", /json/) .expect(200); expect(res.body.message).toBe("Hello, World!"); }); it("should greet the user when a name is provided", async () => { const res = await request(app) .get("/greet?name=John") .expect("Content-Type", /json/) .expect(200); expect(res.body.message).toBe("Hello, John!"); }); });
In the code above, we are using Supertest to send HTTP requests to our app and Jest to write and run the test assertions.
The expect
method is used to check the response status and headers, while Jest's expect
function is used to assert the value of the response body.
Running The Tests
To run the tests, let's jump into the package.json
file that was initialized with pnpm init
and update the scripts > test
property to the following:
{ "scripts": { "test": "jest" } }
You can now run pnpm
test to run the tests. You should see the following output:
$ pnpm test > demo-express-jest-supertest@1.0.0 test /Users/dennisokeeffe/code/projects/demo-express-jest-supertest > jest Determining test su PASS ./app.test.js GET /greet ✓ should greet the world when no name is provided (45 ms) ✓ should greet the user when a name is provided (14 ms) Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total Snapshots: 0 total
Our tests are passing, happy days!
Conclusion
This setup provides a solid foundation to further explore and understand the capabilities of Supertest, Express.js, and Jest in the realm of API testing. As you delve deeper, you'll discover the power and flexibility this combination offers to ensure the reliability and correctness of your APIs.
We demonstrated how to set up a basic Express.js application and write tests using Supertest and Jest. We started with simple tests to assert the response status and then moved onto asserting the response body and its values.
Supertest can be used for far more things than I demonstrated in today's post. It is also great for asserting headers, cookies, and more. I encourage you to check out the Supertest documentation.
References and Further Reading
Photo credit: pecarrolo
Mastering API Testing with Supertest, Express.js, and Jest
Introduction