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.