1. Setting up the Test Environment
Use Jest (the default testing framework in NestJS) or another testing framework of your choice. Import the necessary NestJS modules and create a testing module using @nestjs/testing
.
import { Test, TestingModule } from '@nestjs/testing';
import { MyInterceptor } from './my.interceptor';
import { CallHandler, ExecutionContext } from '@nestjs/common';
import { of } from 'rxjs';
describe('MyInterceptor', () => {
let interceptor: MyInterceptor;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MyInterceptor],
}).compile();
interceptor = module.get(MyInterceptor);
});
it('should be defined', () => {
expect(interceptor).toBeDefined();
});
// ... more tests
});
2. Mocking Dependencies
Interceptors often depend on other services or modules. Use mocking techniques (e.g., Jest's jest.fn()
) to isolate the interceptor's logic and prevent external dependencies from interfering with the tests.
// Example: Mocking a ConfigService
const mockConfigService = {
get: jest.fn().mockReturnValue('some-value'), // Mock the get() method
};
const module: TestingModule = await Test.createTestingModule({
providers: [
MyInterceptor,
{
provide: ConfigService, // Replace ConfigService with the mock
useValue: mockConfigService,
},
],
}).compile();
3. Simulating the Execution Context
The ExecutionContext
provides information about the current request and response. You'll often need to mock this context to simulate different scenarios.
// Example: Mocking the ExecutionContext
const mockExecutionContext: ExecutionContext = {
switchToHttp: () => ({
getRequest: () => ({}), // Mock the request object
getResponse: () => ({}), // Mock the response object
}),
getHandler: jest.fn(),
getClass: jest.fn(),
getType: jest.fn() as any, // Cast to 'any' to avoid strict type errors
};
const mockCallHandler: CallHandler = {
handle: () => of({ data: 'original data' }), // Simulate the next handler
};
5. Testing Error Handling
If your interceptor handles exceptions, test that it correctly catches and handles them. Use try...catch
blocks and expect()
to assert that the correct error is thrown or handled. You can mock the `CallHandler`'s `handle` method to throw an error to simulate an exception.
it('should handle errors', async () => {
const mockCallHandlerWithError: CallHandler = {
handle: () => throwError(() => new Error('Simulated Error')),
};
try {
await interceptor.intercept(mockExecutionContext, mockCallHandlerWithError).toPromise();
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error.message).toEqual('Simulated Error');
}
});