Testing with Supertest
Unlike unit tests, Integration Tests verify that your API routes, controllers, and database work together as a cohesive unit.
1. Why Supertest?
Supertest allows you to make HTTP requests to your app programmatically without actually starting the server on a network port.
2. Writing Your First Test
const request = require('supertest');
const app = require('./app');
describe('GET /api/users', () => {
it('should return all users with 200 OK', async () => {
const res = await request(app).get('/api/users');
expect(res.statusCode).toEqual(200);
expect(res.body.status).toBe('success');
expect(Array.isArray(res.body.data.users)).toBe(true);
});
});
3. Testing POST with Auth
You can chain headers (like Bearer tokens) to test protected routes.
const res = await request(app)
.post('/api/products')
.set('Authorization', 'Bearer ' + token)
.send({ name: 'iPhone', price: 999 });
4. The Test Database
Never run tests against your production database. Use an in-memory database (like mongodb-memory-server) or a dedicated local Test DB that is cleared before each run.
CI/CD Integration: Automate these tests to run every time you push code to GitHub. This prevents you from accidentally breaking your mobile apps or frontend clients with a "simple" change.