Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Learn how to test REST APIs using Supertest with Node.js. Write clean, reliable API tests and integrate them into your CI/CD pipeline easily.

Nandini Pawar
January 11, 2026
Supertest is a Node.js library used to automate API testing by sending HTTP requests and asserting responses. Built on SuperAgent, it integrates smoothly with Express and test runners like Jest or Mocha. You can use it to validate APIs, catch regressions, and ensure backend reliability before code reaches production.
Supertest is a library written in Node.js used for testing HTTP APIs. It extends the SuperAgent HTTP client with a fluent API that allows developers and QA engineers to send requests and make assertions on responses.
Features of Supertest
How to Test REST APIs with Supertest
Supertest is a lightweight Node.js library built for testing HTTP APIs directly and efficiently. It wraps the SuperAgent HTTP client with a fluent, chainable API that’s perfect for integration and end-to-end testing of backend services.
You can pass an http.Server or Express app directly, no need to manage listening ports, as Supertest handles it internally. It works seamlessly with popular JavaScript testing frameworks like Jest, Mocha, and Jasmine, supporting both async/await and promise-based syntax.
Below are the standout features that make Supertest a helpful library for QA engineers:
request(app)
.get('/api/users')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
Fields, bodies, response headers, and custom checks can all be validated inline.
Note: Run your automated tests across 3000+ real browsers. Try TestMu AI Today!
You’ll need Supertest for making requests and a test runner like Jest or Mocha.
Let’s use Jest.
npm install supertest jest --save-dev
Make sure your Express (or other framework) app is exported without starting the server directly in the same file.
Make sure your Express (or other framework) app is exported without starting the server directly in the same file.
For example:
const express = require('express');
const app = express();
app.use(express.json());
app.get('/api/hello', (req, res) => {
res.json({ message: 'Hello, World!' });
});
module.exports = app;
const app = require('./app');
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
This separation allows Supertest to import the app directly without binding to a port.
With Jest, create a test file:
const request = require('supertest');
const app = require('./app');
describe('GET /api/hello', () => {
it('should return a hello message', async () => {
const res = await request(app).get('/api/hello');
expect(res.statusCode).toBe(200);
expect(res.body).toHaveProperty('message', 'Hello, World!');
});
});
Add a Jest test script in the package.json file:
"scripts": {
"test": "jest"
}
Then run the below command to execute your tests:
npm test
Supertest is often introduced as a quick way to test HTTP endpoints in Node.js, but its capabilities extend far beyond basic “send a request and check a status code” scenarios.
Here are some advanced use cases worth knowing about:
Supertest can handle multi-step login processes, token-based auth, and cookie sessions. You can store authentication tokens or cookies from one request and reuse them in subsequent requests.
let token;
beforeAll(async () => {
const res = await request(app)
.post('/login')
.send({ username: 'user', password: 'pass' });
token = res.body.token;
});
test('GET /profile with JWT', async () => {
await request(app)
.get('/profile')
.set('Authorization', `Bearer ${token}`)
.expect(200);
});
This approach allows you to mimic a real client session in your tests.
If your API has workflows (e.g., create -> update -> delete), you can chain requests in a single test to verify data persistence and state changes.
test('Full CRUD flow', async () => {
const createRes = await request(app).post('/items').send({ name: 'test' });
const id = createRes.body.id;
await request(app).put(`/items/${id}`).send({ name: 'updated' }).expect(200);
await request(app).delete(`/items/${id}`).expect(204);
});
This helps catch integration issues that unit tests might miss.
Supertest can simulate multipart/form-data uploads and verify binary responses.
test('Upload and download file', async () => {
await request(app)
.post('/upload')
.attach('file', 'tests/fixtures/sample.txt')
.expect(200);
const res = await request(app)
.get('/download/sample.txt')
.expect('Content-Type', /text/plain/)
.expect(200);
expect(res.text).toContain('Expected content');
});
This is especially useful for APIs handling images, CSVs, or documents.
Integrating Supertest with schema validation libraries like Joi or ajv lets you check that responses match your API contract, preventing silent breaking changes.
const Joi = require('joi');
const userSchema = Joi.object({
id: Joi.number().required(),
name: Joi.string().required(),
});
test('GET /user/:id returns valid schema', async () => {
const res = await request(app).get('/user/1').expect(200);
const { error } = userSchema.validate(res.body);
expect(error).toBeUndefined();
});
QA engineers can apply several well-tested strategies to keep their API suite robust and maintainable:
Mistakes are the bane of test suites. Here are frequent pitfall scenarios to watch out for:
There are plenty of options available, so let’s see how Supertest stacks up against some well-known tools:
| Tool | Type | Best For | Notes |
|---|---|---|---|
| Supertest | Code-based (Node.js) | Automation with full control, CI-ready | Requires JS expertise. No GUI. |
| Postman/Newman | GUI + CLI | Manual exploration, exportable automation | Great for non-dev stakeholders. Less scalable for versioned suites. |
| Insomnia | GUI + CLI | Building requests, team sharing | Similar to Postman. GUI-heavy. |
| Chakram | Code-based (JavaScript) | Fluent assertions, BDD style | No longer actively maintained. Less community support. |
| Frisby.js | Code-based (JavaScript) | JSON-focused API tests using Jest style | Built around fetch, dev momentum slower. |
| PactumJS | Code-based (Node.js) | Contract testing + assert flows | More recent project with DSL-based syntax. |
Pro-tip: If you’re working with REST APIs in Node.js, you’ve probably used Supertest to write detailed tests. It gives you full control over endpoints, assertions, and works seamlessly with test frameworks like Mocha or Jest.
That said, there’s also a growing category of GenAI testing tools like TestMu AI KaneAI that you might find useful if you’re looking to reduce the manual effort of writing API tests. These tools are designed to simplify API test creation by letting you write in natural language commands.
TestMu AI KaneAI is a Generative AI testing tool that allows you to plan, author, debug, and evolve end-to-end tests using natural language commands, eliminating much of the manual coding overhead typically required for test automation.
To get started, check out this guide on API testing with KaneAI.
Supertest brings speed, simplicity, and precision to API testing in Node.js. From setup to advanced usage, it streamlines how QA engineers validate endpoints, handle edge cases, and ensure consistent backend behavior.
With built-in assertion tools, flexible integration with test runners, and best practices for scalable test design, Supertest stands out as a reliable choice for service-level testing. Compared to other tools, it offers a lean, expressive approach without compromising depth.
Did you find this page helpful?
More Related Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance