Integration testing checks if different parts of your NestJS app work well together. It helps find problems between modules or services.
Integration testing in NestJS
describe('YourModule Integration Test', () => { let app: INestApplication; beforeAll(async () => { const moduleRef = await Test.createTestingModule({ imports: [YourModule], }).compile(); app = moduleRef.createNestApplication(); await app.init(); }); afterAll(async () => { await app.close(); }); it('should test something', () => { // your test code here }); });
Use Test.createTestingModule to build a test module with real imports.
Call app.init() to start the NestJS app before tests.
/cats route to ensure it returns status 200.describe('CatsController Integration', () => { let app: INestApplication; beforeAll(async () => { const moduleRef = await Test.createTestingModule({ imports: [CatsModule], }).compile(); app = moduleRef.createNestApplication(); await app.init(); }); afterAll(async () => { await app.close(); }); it('GET /cats returns 200', () => { return request(app.getHttpServer()) .get('/cats') .expect(200); }); });
UserService to check if it creates a user correctly.describe('UserService Integration', () => { let service: UserService; beforeAll(async () => { const moduleRef = await Test.createTestingModule({ imports: [UserModule], }).compile(); service = moduleRef.get<UserService>(UserService); }); it('should create a user', async () => { const user = await service.create({ name: 'Anna' }); expect(user.name).toBe('Anna'); }); });
This integration test starts the full NestJS app from AppModule. It sends a GET request to the root URL and checks if the response is 'Hello World!'. This shows how to test the app's real HTTP behavior.
import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import * as request from 'supertest'; import { AppModule } from '../src/app.module'; describe('AppController (Integration)', () => { let app: INestApplication; beforeAll(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); afterAll(async () => { await app.close(); }); it('/ (GET) should return Hello World', () => { return request(app.getHttpServer()) .get('/') .expect(200) .expect('Hello World!'); }); });
Use supertest to simulate HTTP requests in integration tests.
Integration tests are slower than unit tests but catch more real issues.
Close the app with app.close() to free resources after tests.
Integration testing checks how NestJS parts work together.
Use Test.createTestingModule with real modules and app.init().
Test HTTP routes with supertest for realistic behavior.
Practice
Solution
Step 1: Understand integration testing goal
Integration testing focuses on verifying that multiple parts of the app interact correctly.Step 2: Differentiate from other test types
Unit tests check single functions; performance tests measure speed; syntax checks are done by compilers.Final Answer:
To check how different parts of the application work together -> Option BQuick Check:
Integration testing = check parts working together [OK]
- Confusing integration with unit testing
- Thinking integration tests check performance
- Believing integration tests check code syntax
Solution
Step 1: Recognize correct testing module setup
Use Test.createTestingModule with imports and then compile() to build the module.Step 2: Create app instance and initialize
After compiling, create the app with createNestApplication() then call app.init() to start the NestJS app for testing.Final Answer:
const app = (await Test.createTestingModule({ imports: [AppModule] }).compile()).createNestApplication(); await app.init(); -> Option DQuick Check:
compile() -> createNestApplication() -> init() [OK]
- Calling init() directly on createTestingModule
- Using start() method which does not exist
- Not compiling the testing module before init
const response = await request(app.getHttpServer()).get('/users');
expect(response.status).toBe(200);Solution
Step 1: Understand the test request
The test sends a GET request to '/users' route using supertest on the initialized app.Step 2: Check expected status code
The test expects the response status to be 200, meaning success and route exists.Final Answer:
200 -> Option AQuick Check:
GET /users returns 200 success [OK]
- Confusing 404 (not found) with 200
- Assuming 500 error without error in code
- Mixing authentication errors with route success
let app;
beforeAll(async () => {
app = Test.createTestingModule({ imports: [AppModule] });
await app.init();
});Solution
Step 1: Identify missing compile() call
Test.createTestingModule returns a builder; you must call compile() to get the module instance.Step 2: Understand why getHttpServer is undefined
Without compile(), app is not a proper module instance, so app.getHttpServer is undefined causing the error.Final Answer:
Forgot to call compile() before init() -> Option AQuick Check:
compile() needed before init() [OK]
- Skipping compile() step
- Confusing beforeAll with beforeEach for setup
- Assuming missing imports cause this error
Solution
Step 1: Setup full app for integration test
Integration tests require the full app context, so createTestingModule with AppModule, compile, and init the app.Step 2: Use supertest to send POST request
Use supertest to send a POST request with JSON data to the '/users' route to test real HTTP behavior.Final Answer:
Use Test.createTestingModule with AppModule, compile and init app, then use supertest to POST JSON to '/users' endpoint -> Option CQuick Check:
Integration test = full app + supertest POST [OK]
- Testing controller methods directly without app context
- Using mocks instead of real modules for integration tests
- Confusing unit tests with integration tests
Ready to prove it?
Pass the test and this pattern moves unknown
