When it comes to testing APIs in JavaScript, there are various frameworks available. Each serves different purposes, making it important to understand what, where, when, and why to use them. In this guide, we’ll explore API testing using two powerful combinations: Jest + Supertest and Mocha + Chai + Sinon, with simple code examples to get you started.
What is API Testing?
API testing involves sending requests to your API endpoints and checking whether the responses match expectations. This ensures that your API behaves correctly, handling various actions like fetching, creating, or deleting data.
Why Use Testing Frameworks for API Testing?
- Ensure Correct Responses: When your API is called, it should respond with the correct data or error message.
- Catch Bugs Early: API testing helps find problems in your server logic before releasing the code to production.
- Automate the Process: You can run tests automatically, saving time and ensuring that everything still works after updates.
- Confidence in Refactoring: Refactoring your API is less risky when you have tests to verify everything works as expected.
When and Where Should You Use API Testing Frameworks?
- When: You should write API tests during development, after creating or updating your API endpoints.
- Where: You can test various parts of your API, like data retrieval (
GET
), data creation (POST
), or data updates (PUT
).
Popular API Testing Frameworks
There are many frameworks for API testing, but here are two effective combinations:
- Jest + Supertest: Simple setup for API testing, great for beginners.
- Mocha + Chai + Sinon: Offers flexibility and powerful tools for more complex tests.
Prerequisites: Setting Up Your Environment
Before diving into API testing, it’s important to ensure that your development environment is properly set up. Here’s what you need to do:
Step 1: Install Node.js and npm
Node.js is a JavaScript runtime that allows you to run JavaScript code on the server side. It comes with npm (Node Package Manager), which helps you install and manage packages.
Installation Steps:
- Download and install Node.js from the official website.
- To verify the installation, open your terminal and run:
node -v
npm -v
This should display the installed versions of Node.js and npm.
Step 2: Create a New Project Directory
Open your terminal and create a new directory for your project. Navigate into that directory:
mkdir api-testing-example
cd api-testing-example
Alternatively, you can create a new directory using the file explorer and then open the terminal in that location.
Step 3: Initialize a New Node.js Project
Run the following command to create a package.json
file, which will manage your project dependencies:
npm init -y
The -y
flag automatically answers "yes" to all prompts, creating a default package.json
file.
Step 4: Open the Project Directory in Your Code Editor
Open the project directory you just created in your code editor of choice. If you do not have one yet, I recommend using Visual Studio Code (VS Code). Additionally, you can explore the following extensions in VS Code that are tailored for testing frameworks:


Getting Started: Jest + Supertest
We’ll first look at Jest (a popular testing framework) and Supertest (a library for testing HTTP endpoints).
Step 1: Set Up a Simple API
First, let’s build a simple API using Express, a framework for building web servers.
1. Install dependencies:
npm install express jest supertest --save-dev
2. Create a file app.js
for the API:
// app.js
const express = require('express');
const app = express();
app.use(express.json());
const users = [{ id: 1, name: 'John Doe' }];
app.get('/users', (req, res) => {
res.status(200).json(users);
});
app.post('/users', (req, res) => {
const newUser = { id: users.length + 1, name: req.body.name };
users.push(newUser);
res.status(201).json(newUser);
});
module.exports = app;
This API has two endpoints:
GET /users
: Returns a list of users.POST /users
: Adds a new user.
Step 2: Write API Tests Using Jest + Supertest
Now, let’s write tests for this API.
1. Create the test file app.test.js
:
// app.test.js
const request = require('supertest');
const app = require('./app');
describe('API Tests', () => {
it('GET /users should return a list of users', async () => {
const res = await request(app).get('/users');
expect(res.statusCode).toBe(200);
expect(res.body.length).toBeGreaterThan(0);
});
it('POST /users should create a new user', async () => {
const res = await request(app)
.post('/users')
.send({ name: 'Jane Doe' });
expect(res.statusCode).toBe(201);
expect(res.body.name).toBe('Jane Doe');
});
});
Step 3: Run the Tests
You can now run the tests:
npx jest
Jest will run your tests and show whether the API is working as expected.
Understanding the Terms
- Jest: A testing framework that allows you to write and run tests.
- Supertest: A library used for testing HTTP requests like
GET
,POST
, etc. - describe: Groups tests together. For example, you can group all API tests under
describe('API Tests')
. - it: Defines an individual test. For example,
it('GET /users should return a list of users')
. - expect: Checks if the result matches your expectation. For example,
expect(res.statusCode).toBe(200)
checks if the response status is 200 (OK).
Advanced API Testing: Mocha + Chai + Sinon
If you need more flexibility, you can use Mocha (a testing framework), Chai (an assertion library), and Sinon (a library for mocking/stubbing).
Step 1: Set Up a Simple API
We’ll use the same API as before.
Step 2: Write API Tests Using Mocha + Chai
1. Install dependencies:
npm install mocha chai sinon supertest --save-dev
2. Create the test file app.test.js
:
// app.test.js
const request = require('supertest');
const { expect } = require('chai');
const sinon = require('sinon');
const app = require('./app');
describe('API Tests', () => {
it('GET /users should return a list of users', (done) => {
request(app)
.get('/users')
.end((err, res) => {
expect(res.statusCode).to.equal(200);
expect(res.body.length).to.be.greaterThan(0);
done();
});
});
it('POST /users should create a new user', (done) => {
request(app)
.post('/users')
.send({ name: 'Jane Doe' })
.end((err, res) => {
expect(res.statusCode).to.equal(201);
expect(res.body.name).to.equal('Jane Doe');
done();
});
});
});
Step 3: Using Sinon (optional)
What is Sinon?
Sinon is a library that helps you mock, spy, or stub functions in your code. It’s useful when you want to:
- Stub external dependencies (e.g., databases, third-party APIs) to simulate their behavior without actually making calls to them.
- Spy on how functions are called, keeping track of how many times they were called and with what arguments.
- Mock behavior to simulate different responses or actions for testing purposes.
How Could Sinon Be Used in This Example?
In your test, you might want to avoid actually making changes to the real API or database. You can use Sinon to stub the logic inside your API to control how it behaves during testing.
Example: Stubbing a Database Call with Sinon
Let’s say you have a users
array in your API and you want to simulate adding a user without modifying the real data. You can use Sinon to stub the part of the code that handles adding users.
1. Modify the API to extract user operations: Let’s say the user creation logic is inside a function addUser
:
// app.js
const express = require('express');
const app = express();
app.use(express.json());
let users = [{ id: 1, name: 'John Doe' }];
const addUser = (name) => {
const newUser = { id: users.length + 1, name };
users.push(newUser);
return newUser;
};
app.get('/users', (req, res) => {
res.status(200).json(users);
});
app.post('/users', (req, res) => {
const newUser = addUser(req.body.name);
res.status(201).json(newUser);
});
module.exports = { app, addUser }; // Export addUser for testing
2. Stub the addUser
function using Sinon: In your test, you can now stub the addUser
function so it behaves differently during the test:
// app.test.js
const request = require('supertest');
const { expect } = require('chai');
const sinon = require('sinon');
const { app, addUser } = require('./app'); // Import addUser
describe('API Tests with Sinon', () => {
let addUserStub;
beforeEach(() => {
// Stub addUser before each test
addUserStub = sinon.stub().returns({ id: 999, name: 'Stubbed User' });
});
it('POST /users should create a new user with stubbed data', (done) => {
sinon.replace(addUser, 'addUser', addUserStub); // Replace the original function with the stub
request(app)
.post('/users')
.send({ name: 'Jane Doe' })
.end((err, res) => {
expect(res.statusCode).to.equal(201);
expect(res.body.id).to.equal(999); // Check the stubbed data
expect(res.body.name).to.equal('Stubbed User');
done();
});
sinon.restore(); // Restore the original addUser function after the test
});
afterEach(() => {
sinon.restore(); // Clean up after each test
});
});
Explanation:
- sinon.stub(): This creates a stub for the
addUser
function. A stub replaces a function with a custom implementation—in this case, it always returns{ id: 999, name: 'Stubbed User' }
. - sinon.replace(): Replaces the actual
addUser
function in the API with the stub for this test. - sinon.restore(): Restores the original function after the test is done, to avoid interfering with other tests.
Use Cases for Sinon:
- Mocking dependencies: If your API depends on a database or an external service, you can mock those dependencies during tests to avoid making real API calls or database changes.
- Spying on function calls: You can spy on functions to check how many times they were called or what arguments they received.
- Simulating errors: You can make a function throw an error to test how your API handles failure scenarios.
Step 4: Run the Tests
Run the tests using:
npx mocha
Understanding the Terms
- Mocha: A testing framework that runs your tests.
- Chai: An assertion library that lets you write human-readable checks like
expect(res.statusCode).to.equal(200)
. - Sinon: A tool for mocking or stubbing, useful for simulating API responses without actually hitting the real server.
- done: A callback used in asynchronous tests (e.g., making an API request) to signal when the test is finished.
When to Use These Frameworks
- Jest + Supertest: Best for beginners and when you want a simple, easy-to-setup solution for API testing.
- Mocha + Chai + Sinon: Ideal for more complex testing needs where you might need to mock or stub parts of your API.
Conclusion
Both Jest + Supertest and Mocha + Chai + Sinon are powerful combinations for API testing. While Jest is great for quick and simple tests, Mocha with Chai and Sinon offers more flexibility for advanced scenarios. Try the code examples above to get a feel for API testing and choose the setup that works best for your project!
Comments
Post a Comment