Boot the Real App, Hit It With supertest
End-to-End Testing
e2e tests start the full module tree and make real HTTP calls — they catch the wiring bugs unit tests miss.
What you'll learn
- Set up an e2e Jest config under test/
- Boot the app with createTestingModule + createNestApplication
- Use supertest to assert on real responses
Unit tests prove your services do what you think. End-to-end tests prove
the whole module tree actually wires up — routes, pipes, guards, filters
and all. nest new ships an e2e setup already.
The Layout
test/
app.e2e-spec.ts
jest-e2e.json jest-e2e.json points Jest at *.e2e-spec.ts files and uses a separate
config from your unit tests.
A Minimal e2e Spec
import { INestApplication, ValidationPipe } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
describe('Users (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleRef.createNestApplication();
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
await app.init();
});
afterAll(() => app.close());
it('GET /users -> []', () => {
return request(app.getHttpServer())
.get('/users')
.expect(200)
.expect([]);
});
it('POST /users validates the body', () => {
return request(app.getHttpServer())
.post('/users')
.send({ email: 'not-an-email' })
.expect(400);
});
}); app.getHttpServer() returns the underlying Node HTTP server, which
supertest can call without binding a port.
Use A Test Database
Run migrations against a throwaway database before the suite, then truncate
between tests. Docker Compose plus a globalSetup file is a common pattern:
// test/global-setup.ts
import { execSync } from 'node:child_process';
export default async () => {
execSync('npm run db:migrate', { stdio: 'inherit' });
}; Override Providers For Speed
You do not have to use the real database. Swap any provider with a mock
using .overrideProvider(MailService).useValue(stub) on the testing
module builder — perfect for outbound integrations.