How to Test Express API: Simple Guide with Examples
To test an
Express API, use Supertest to simulate HTTP requests and Jest as the test runner. Write tests that call your API routes and check responses for expected status codes and data.Syntax
Testing an Express API typically involves importing your app, then using Supertest to send HTTP requests. You write test cases with Jest that describe what each test should check.
request(app): Starts a test request to your Express app..get('/path'): Sends a GET request to the specified path..expect(statusCode): Checks the response status code..then(response => { ... }): Handles the response to check body or headers.
javascript
import request from 'supertest'; import app from './app'; test('GET /endpoint returns 200', async () => { await request(app) .get('/endpoint') .expect(200) .then(response => { // check response body here }); });
Example
This example shows a simple Express app with one route and a test that checks if the route returns status 200 and the expected JSON response.
javascript
import express from 'express'; import request from 'supertest'; // Create Express app const app = express(); app.get('/hello', (req, res) => { res.json({ message: 'Hello, world!' }); }); // Test suite describe('GET /hello', () => { it('should respond with JSON containing message', async () => { const response = await request(app).get('/hello').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 the Express app instance separately from the server start code can make testing harder.
- Forgetting to use
async/awaitor return promises in tests can cause false positives. - Not closing server or database connections after tests can cause hanging tests.
- Testing only status codes without checking response body may miss bugs.
javascript
/* Wrong: Starting server inside test file */ import express from 'express'; const app = express(); app.get('/', (req, res) => res.send('Hi')); app.listen(3000); // Avoid this in test files /* Right: Export app and test without starting server */ import express from 'express'; const app = express(); app.get('/', (req, res) => res.send('Hi')); export default app; // In test file import request from 'supertest'; import app from './app'; test('GET / returns Hi', async () => { await request(app).get('/').expect(200, 'Hi'); });
Quick Reference
Use this quick checklist when testing Express APIs:
- Export your Express app without calling
app.listen(). - Use
Supertestto simulate HTTP requests. - Use
Jestor another test runner to organize tests. - Check both status codes and response bodies.
- Use
async/awaitor return promises in tests. - Clean up resources after tests if needed.
Key Takeaways
Use Supertest with Jest to write clear, automated tests for Express APIs.
Always export your Express app separately from server startup for easy testing.
Check both HTTP status codes and response data in your tests.
Use async/await or return promises to ensure tests run correctly.
Avoid starting the server inside test files to prevent conflicts.