Nestjs testing skill

Write Unit and E2E tests with Jest, mocking strategies, and database isolation in NestJS.

by HoangNguyen0403·MIT license·★ 569 Stars on the repo·GitHub ↗

Use now

Files of Nestjs testing

HoangNguyen0403/develop1 file shown
SKILL.md
Show the full text72 lines

NestJS Testing

Priority: P2 (MEDIUM)

Core Rule Anchors

  • [BE-TEST-01] Parameterized Tests for Equivalent Cases: Prefer test.each when methods have multiple equivalent inputs or boundary permutations. Distinct scenarios may stay separate test functions. Reviewers must not demand parameterized rewrites without a behavioral gap.
  • [BE-TEST-02] Ban on Brittle DB Mock String Matching: Do not use string-matching mocks for raw SQL queries. Test pure domain calculations directly, or use a real test DB for repository verification.
  • [BE-TEST-03] Ban on Shallow Assertions: Never assert only expect(res).toBeDefined() without inspecting payload fields, status codes, and invariants.
  • [BE-TEST-04] Ban on Pass-Through Interface Mocks: Repositories and service handlers must test contract compliance and error mapping. Ban 1:1 pass-through mock echoing without contract assertions.
  • [BE-TEST-05] Bug-First Regression Lock: Every PR fixing a bug ticket or with title fix(...) must introduce a test reproducing the defect prior to the fix.

Structure

src/**/*.spec.ts      # Unit tests (isolated logic)
test/**/*.e2e-spec.ts # E2E tests (full app flows)

Unit Testing

  • Setup & Mocks ([BE-TEST-04]): Use Test.createTestingModule() with mocked providers. Ban 1:1 pass-through mock echoing.
  • Pattern & Cleanup: AAA (Arrange-Act-Assert). Call jest.clearAllMocks() in afterEach.
  • Assertions ([BE-TEST-03]): Avoid shallow assertions like expect(res).toBeDefined(). Verify payload invariants.
  • Coverage: Coverage is diagnostic and project-configured; verify risk-weighted critical paths rather than padding code for an arbitrary percentage.

E2E Testing

  • Database ([BE-TEST-02]): Use real test DB (Docker). Never mock DB in E2E.
  • Cleanup: Mandatory. Use transaction rollback or TRUNCATE in afterEach.
  • App Init: Create app in beforeAll, close in afterAll.
  • Guards: Override via .overrideGuard(X).useValue({ canActivate: () => true }).

Strict TypeScript (MANDATORY)

  • No any: Use typed objects, jest.Mocked<T>, or as unknown as T. Never as any.
  • No eslint-disable: Fix underlying type issue. No exceptions.
  • Verify DTO shapes: Read actual DTO class before writing mock data.
  • Cast Jest matchers: Nested expect.anything() → expect.anything() as unknown.
  • No unused vars: Only declare variables if referenced in assertions or setup.

Anti-Patterns

  • [BE-TEST-01] Stylistic parameterized rewrites: Do not demand test.each rewrites without a behavioral gap.
  • [BE-TEST-02] Brittle DB mock string matching: Do not match SQL strings in mocks; use real DB.
  • [BE-TEST-03] Shallow assertions: Ban shallow assertions like expect(res).toBeDefined().
  • [BE-TEST-04] Pass-through mock echoing: Ban 1:1 mock echoing without contract assertions.
  • [BE-TEST-05] Bug fix without reproduction test: Ban bug fixes without a reproduction test.
  • No Private Tests: Test via public methods, not service['privateMethod']. Never write tests for private methods solely to satisfy coverage targets.
  • No DB Mocks in E2E: Use real DB with cleanup. Mocks defeat E2E purpose.
  • No Shared State: Call jest.clearAllMocks() in afterEach. Random failures otherwise.
  • No Resource Leaks: Always close app and DB in afterAll.

References

Setup examples, mocking patterns, E2E flows, test builders, coverage config: references/patterns.md

Strict-TypeScript patterns (Jest matchers, mock typing, DTO verification): references/strict-typescript-testing.md

1---
2name: nestjs-testing
3description: Write Unit and E2E tests with Jest, mocking strategies, and database isolation in NestJS. Use when writing NestJS unit tests, E2E tests with supertest, or mock providers.
4metadata:
5 triggers:
6 files:
7 - '**/*.spec.ts'
8 - 'test/**/*.e2e-spec.ts'
9 - 'Test.createTestingModule'
10 keywords:
11 - supertest
12 - jest
13 - beforeEach
14---
15# NestJS Testing
16 
17## **Priority: P2 (MEDIUM)**
18## Core Rule Anchors
19 
20- **`[BE-TEST-01]` Parameterized Tests for Equivalent Cases**: Prefer `test.each` when methods have multiple equivalent inputs or boundary permutations. Distinct scenarios may stay separate test functions. Reviewers must not demand parameterized rewrites without a behavioral gap.
21- **`[BE-TEST-02]` Ban on Brittle DB Mock String Matching**: Do not use string-matching mocks for raw SQL queries. Test pure domain calculations directly, or use a real test DB for repository verification.
22- **`[BE-TEST-03]` Ban on Shallow Assertions**: Never assert only `expect(res).toBeDefined()` without inspecting payload fields, status codes, and invariants.
23- **`[BE-TEST-04]` Ban on Pass-Through Interface Mocks**: Repositories and service handlers must test contract compliance and error mapping. Ban 1:1 pass-through mock echoing without contract assertions.
24- **`[BE-TEST-05]` Bug-First Regression Lock**: Every PR fixing a bug ticket or with title `fix(...)` must introduce a test reproducing the defect prior to the fix.
25 
26## Structure
27 
28```
29src/**/*.spec.ts # Unit tests (isolated logic)
30test/**/*.e2e-spec.ts # E2E tests (full app flows)
31```
32 
33## Unit Testing
34 
35- **Setup & Mocks (`[BE-TEST-04]`)**: Use `Test.createTestingModule()` with mocked providers. Ban 1:1 pass-through mock echoing.
36- **Pattern & Cleanup**: AAA (Arrange-Act-Assert). Call `jest.clearAllMocks()` in `afterEach`.
37- **Assertions (`[BE-TEST-03]`)**: Avoid shallow assertions like `expect(res).toBeDefined()`. Verify payload invariants.
38- **Coverage**: Coverage is diagnostic and project-configured; verify risk-weighted critical paths rather than padding code for an arbitrary percentage.
39 
40## E2E Testing
41 
42- **Database (`[BE-TEST-02]`)**: Use real test DB (Docker). Never mock DB in E2E.
43- **Cleanup**: Mandatory. Use transaction rollback or `TRUNCATE` in `afterEach`.
44- **App Init**: Create app in `beforeAll`, close in `afterAll`.
45- **Guards**: Override via `.overrideGuard(X).useValue({ canActivate: () => true })`.
46 
47## Strict TypeScript (MANDATORY)
48 
49- **No `any`**: Use typed objects, `jest.Mocked<T>`, or `as unknown as T`. Never `as any`.
50- **No `eslint-disable`**: Fix underlying type issue. No exceptions.
51- **Verify DTO shapes**: Read actual DTO class before writing mock data.
52- **Cast Jest matchers**: Nested `expect.anything()` → `expect.anything() as unknown`.
53- **No unused vars**: Only declare variables if referenced in assertions or setup.
54 
55## Anti-Patterns
56 
57- **`[BE-TEST-01]` Stylistic parameterized rewrites**: Do not demand `test.each` rewrites without a behavioral gap.
58- **`[BE-TEST-02]` Brittle DB mock string matching**: Do not match SQL strings in mocks; use real DB.
59- **`[BE-TEST-03]` Shallow assertions**: Ban shallow assertions like `expect(res).toBeDefined()`.
60- **`[BE-TEST-04]` Pass-through mock echoing**: Ban 1:1 mock echoing without contract assertions.
61- **`[BE-TEST-05]` Bug fix without reproduction test**: Ban bug fixes without a reproduction test.
62- **No Private Tests**: Test via public methods, not service['privateMethod']. Never write tests for private methods solely to satisfy coverage targets.
63- **No DB Mocks in E2E**: Use real DB with cleanup. Mocks defeat E2E purpose.
64- **No Shared State**: Call `jest.clearAllMocks()` in `afterEach`. Random failures otherwise.
65- **No Resource Leaks**: Always close app and DB in `afterAll`.
66## References
67 
68Setup examples, mocking patterns, E2E flows, test builders, coverage config:
69[references/patterns.md](references/patterns.md)
70 
71Strict-TypeScript patterns (Jest matchers, mock typing, DTO verification):
72[references/strict-typescript-testing.md](references/strict-typescript-testing.md)

Discussion

Alternatives