How to Use Supertest with Express for API Testing
Use
supertest by importing it and passing your Express app to it. Then, chain HTTP methods like .get() or .post() with assertions to test your API endpoints easily.Syntax
The basic syntax involves importing supertest and your Express app, then calling request(app) to start a test. You chain HTTP methods like .get(path) or .post(path) and use .expect() to check status codes or response data.
request(app): Initializes Supertest with your Express app..get('/path'): Sends a GET request to the specified path..post('/path'): Sends a POST request..expect(status): Checks the HTTP status code..expect(body): Checks the response body..end(callback): Optional callback to finish the test.
javascript
import request from 'supertest'; import app from './app'; describe('GET /endpoint', () => { it('responds with status 200', async () => { await request(app) .get('/endpoint') .expect(200) .expect('Content-Type', /json/); }); });
Example
This example shows a simple Express app with one GET route and a test using Supertest to check if the route returns status 200 and the expected JSON response.
javascript
import express from 'express'; import request from 'supertest'; const app = express(); app.get('/hello', (req, res) => { res.json({ message: 'Hello, world!' }); }); describe('GET /hello', () => { it('should respond with JSON containing message', async () => { const response = await request(app) .get('/hello') .expect('Content-Type', /json/) .expect(200); expect(response.body).toEqual({ message: 'Hello, world!' }); }); });
Output
PASS ./app.test.js
GET /hello
✓ should respond with JSON containing message (XX ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XX s
Common Pitfalls
- Not exporting your Express app properly can cause Supertest to fail.
- Forgetting to use
awaitor return the Supertest call in async tests can make tests pass incorrectly. - Not setting
Content-Typeheaders when sending JSON requests can cause unexpected failures. - Using
.end()callback andasync/awaittogether can cause confusion; preferasync/awaitfor clarity.
javascript
/* Wrong: Missing await, test may pass without running request */ test('GET /hello missing await', () => { return request(app) .get('/hello') .expect(200); }); /* Right: Using await to ensure test waits for request */ test('GET /hello with await', async () => { await request(app) .get('/hello') .expect(200); });
Quick Reference
Here is a quick summary of common Supertest methods used with Express:
| Method | Description |
|---|---|
| request(app) | Initialize Supertest with your Express app |
| .get(path) | Send a GET request to the path |
| .post(path) | Send a POST request to the path |
| .send(data) | Send JSON or form data in the request body |
| .set(header, value) | Set HTTP headers for the request |
| .expect(status) | Assert the HTTP status code |
| .expect(header, value) | Assert a response header |
| .expect(body) | Assert the response body content |
| .end(callback) | Optional callback to finish the test |
Key Takeaways
Import Supertest and pass your Express app to start testing endpoints.
Use async/await with Supertest calls to ensure tests run correctly.
Check status codes and response bodies with .expect() methods.
Export your Express app without listening to allow Supertest to handle requests.
Avoid mixing callbacks and async/await for clearer test code.