From harness-claude
Tests NestJS services, controllers, and full apps using Test.createTestingModule for unit/integration, Jest mocks, overrideProvider, and Supertest e2e. For mocking dependencies, guards, and HTTP testing.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Test NestJS apps with Test.createTestingModule, jest mocks, supertest e2e, and overrideProvider
Builds reliable Jest test suites for NestJS modules, services, and controllers covering unit, integration, and e2e tests. Use for TestModule setup, mocking providers, database fakes, and debugging flaky tests.
Provides NestJS testing examples for unit tests with TestingModule, repository/service mocks, custom providers, and controller testing. For building well-tested apps.
Creates and configures NestJS modules, controllers, services, DTOs, guards, and interceptors for TypeScript backend apps. Use for REST/GraphQL APIs, dependency injection, JWT/Passport auth, Prisma/TypeORM integration, validation, Swagger docs, and testing.
Share bugs, ideas, or general feedback.
Test NestJS apps with Test.createTestingModule, jest mocks, supertest e2e, and overrideProvider
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);
});
});
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);
});
});
// 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);
});
});
.overrideGuard(JwtAuthGuard).useValue({ canActivate: () => true })
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.
overrideProvider vs direct mock value: 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.
mockDeep from jest-mock-extended: Prisma's generated client is deeply nested. 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.
app.init() vs app.listen(): For supertest, call 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.
https://docs.nestjs.com/fundamentals/testing