install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/nestjs-testing-patterns" ~/.claude/skills/intense-visions-harness-engineering-nestjs-testing-patterns-3d2bb4 && rm -rf "$T"
manifest:
agents/skills/codex/nestjs-testing-patterns/SKILL.mdsource content
NestJS Testing Patterns
Test NestJS apps with Test.createTestingModule, jest mocks, supertest e2e, and overrideProvider
When to Use
- You are writing unit tests for a service and need to mock its dependencies
- You are writing integration tests for a controller and need to spin up a partial NestJS app
- You are writing e2e tests that exercise real HTTP requests against the running application
- You need to verify that guards, interceptors, or pipes behave correctly in context
Instructions
- Unit test a service — mock all dependencies:
describe('UsersService', () => { let service: UsersService; let prisma: DeepMockProxy<PrismaClient>; beforeEach(async () => { const module = await Test.createTestingModule({ providers: [UsersService, { provide: PrismaService, useValue: mockDeep<PrismaClient>() }], }).compile(); service = module.get(UsersService); prisma = module.get(PrismaService); }); it('throws NotFoundException when user does not exist', async () => { prisma.user.findUnique.mockResolvedValue(null); await expect(service.findOne('missing-id')).rejects.toThrow(NotFoundException); }); });
- Integration test a controller with overrideProvider:
describe('UsersController (integration)', () => { let app: INestApplication; let usersService: jest.Mocked<UsersService>; beforeAll(async () => { const module = await Test.createTestingModule({ controllers: [UsersController], providers: [UsersService], }) .overrideProvider(UsersService) .useValue({ findOne: jest.fn(), create: jest.fn() }) .compile(); app = module.createNestApplication(); app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true })); await app.init(); usersService = module.get(UsersService); }); afterAll(() => app.close()); it('GET /users/:id returns 200', async () => { usersService.findOne.mockResolvedValue({ id: '1', email: 'a@b.com' } as User); return request(app.getHttpServer()).get('/users/1').expect(200); }); });
- E2e test against the real application:
// test/app.e2e-spec.ts describe('AppController (e2e)', () => { let app: INestApplication; beforeAll(async () => { const module = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = module.createNestApplication(); await app.init(); }); it('POST /users returns 201', () => { return request(app.getHttpServer()) .post('/users') .send({ email: 'test@example.com', password: 'password123' }) .expect(201); }); });
- Mock a guard in tests:
.overrideGuard(JwtAuthGuard).useValue({ canActivate: () => true })
Details
NestJS testing is built on Jest, with
@nestjs/testing providing Test.createTestingModule() which creates an isolated module context — no HTTP server, no port binding. Providers, guards, pipes, and interceptors can all be selectively replaced.
vs direct mock value: overrideProvider
overrideProvider(Token).useValue(mock) replaces the registered provider in the module without changing the module definition. This is cleaner than passing mock values in providers because it works even when the token is registered in an imported module.
from jest-mock-extended: Prisma's generated client is deeply nested. mockDeep
mockDeep<PrismaClient>() creates a deep mock where every method is a jest.fn(). Pair with { provide: PrismaService, useValue: mockDeep<PrismaClient>() }.
Guard overrides:
overrideGuard(MyGuard).useValue({ canActivate: () => true }) bypasses the guard entirely. To test the guard itself, instantiate it directly and call canActivate() with a mock ExecutionContext.
vs app.init()
: For supertest, call app.listen()
app.init() — it sets up the application without starting a TCP server. supertest(app.getHttpServer()) binds directly to the HTTP handler.
Test isolation: Use
beforeEach to recreate the module for unit tests (avoids state leakage between tests). Use beforeAll for e2e tests (app startup is expensive). Always call app.close() in afterAll to avoid open handle warnings.
Source
https://docs.nestjs.com/fundamentals/testing
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.