Testing, Documentation, and Production DeploymentLesson 6.1
Integration testing Express APIs with Jest and Supertest
Jest setup, Supertest, describe and it blocks, beforeAll and afterAll, HTTP assertions, testing status codes and response bodies, test database, teardown
Integration Testing with Jest and Supertest
Integration tests send real HTTP requests to your Express app and assert on the response. They catch bugs that unit tests miss because they exercise the full middleware-route-controller-database stack.
Setup
npm install --save-dev jest supertest
# In package.json:
"scripts": { "test": "jest --detectOpenHandles" }// app.js โ export app WITHOUT calling listen
const express = require('express');
const app = express();
// ... routes, middleware ...
module.exports = app;
// index.js โ only file that calls listen
const app = require('./app');
app.listen(3000);Writing Tests
// tests/users.test.js
const request = require('supertest');
const app = require('../app');
describe('GET /users', () => {
it('returns 200 with an array', async () => {
const res = await request(app).get('/users');
expect(res.status).toBe(200);
expect(Array.isArray(res.body.data)).toBe(true);
});
it('returns 404 for unknown user', async () => {
const res = await request(app).get('/users/99999');
expect(res.status).toBe(404);
expect(res.body.error).toBeDefined();
});
it('creates a user with valid data', async () => {
const res = await request(app).post('/users')
.send({ name: 'Test User', email: 'test@example.com' });
expect(res.status).toBe(201);
expect(res.body.email).toBe('test@example.com');
});
});Export app without calling listen โ Supertest handles binding. Use a separate test database or reset in-memory state in beforeEach.
