unit-testing
Backend Unit Testing Skill
This skill provides a comprehensive framework for writing high-quality unit tests for NestJS backend services using Jest. It is organized into reference documents for easy lookup during test development.
Workflow
When writing unit tests, follow this order:
┌────────────────────────────────────────────────────────────┐
│ 0. PLAN tests → Mandatory Phase │
│ 1. CONFIRM plan → Get User Approval First │
│ 2. READ basic rules → Mandatory for every test │
│ 3. WRITE happy path tests → Service + Controller │
│ 4. READ edge cases → Required for business logic │
│ 5. WRITE edge case tests → Boundaries, errors, caching │
│ 6. RUN coverage → Must meet 80% threshold │
│ 7. GENERATE final report → Mandatory output format │
└────────────────────────────────────────────────────────────┘
Planning Phase (Mandatory)
Before writing any test code, you MUST create a testing plan, save it as a file, and GET USER CONFIRMATION. This ensures comprehensive coverage before implementation begins.
Implementation Plan Storage
- Export as Markdown: Save the plan as a
.mdfile in the repository root. - Naming Convention:
UT_Imp_Plan_<subject>_<YYYYMMDD>_<HHMMSS>.md(e.g.,UT_Imp_Plan_UsersService_20260312_122259.md).
The plan should outline:
- The class and methods to be tested.
- Key dependencies to be mocked.
- Categorized test scenarios (Happy Path, Error Path, Edge Cases).
[!IMPORTANT] DO NOT proceed to implementation (Step 2) until the plan is saved to the repo root and the user has approved it.
Refer to the Basic Rules and Edge Cases checklists during planning.
References
This skill is split into two reference documents. You MUST read the relevant reference before writing tests.
📘 Basic Rules
Read first — applies to ALL unit tests.
Covers:
- File placement & naming (
.spec.tsco-located with source) - Test structure — AAA pattern (Arrange → Act → Assert)
describeblock organization by method- Test naming:
should [behavior] when [condition] Test.createTestingModulesetup for services & controllers- Mocking rules (mock all deps, reset in
beforeEach) - What to test per layer (services, controllers, DTOs)
- Assertion best practices & async exception patterns
- Test independence rules
- Coverage thresholds (80% lines/functions)
📕 Edge Cases
Read second — required for any method with business logic.
Covers:
- Null, undefined & empty value handling
- Boundary value analysis (numeric, string, pagination)
- Error propagation & exception type verification
- Caching edge cases (hit, miss, TTL expiry)
- Time-sensitive logic (
jest.useFakeTimers) - Concurrent & async patterns (Promise.allSettled, race conditions)
- Special characters (unicode, SQL injection, emoji)
- Filter & query combination testing
- Large dataset volume testing
- Comprehensive edge case checklist
Quick Decision Guide
| Scenario | What to read |
|---|---|
Writing any new *.spec.ts file |
Basic Rules |
| Testing a simple CRUD controller | Basic Rules only |
| Testing a service with business rules | Basic Rules + Edge Cases |
| Testing a service with caching/TTL | Basic Rules + Edge Cases §4 |
| Testing date-dependent filtering | Basic Rules + Edge Cases §5 |
| Reviewing an existing test file | Both — use the checklists |
Minimum Test Requirements
Every module must have:
| File | Tests Required |
|---|---|
*.service.spec.ts |
Happy path + error path per public method. Edge cases for business logic. |
*.controller.spec.ts |
Delegation + error propagation per endpoint. |
Coverage Thresholds (Enforced)
| Metric | Minimum |
|---|---|
| Branches | 70% |
| Functions | 80% |
| Lines | 80% |
| Statements | 80% |
Running Tests
# All unit tests
npm run test
# Specific module
npx jest --testPathPattern="users"
# TDD watch mode
npx jest --watch --testPathPattern="users"
# Coverage report
npm run test:cov
Final Output Format
Upon completion of the unit testing task, you MUST provide a summary report in the following format.
Report Export Requirements
- Export as Markdown: Create a
.mdfile in the repository root containing the report. - Naming Convention:
UT_<subject>_<YYYYMMDD>_<HHMMSS>.md(e.g.,UT_UsersService_20240312_111536.md). - Metadata Header: The file must start with:
Subject: <name> Generated: YYYY-MM-DD HH:MM:SS
1. Changes Summary
Briefly list the files created or modified.
2. Test Scenarios Summary
Provide a table for each file tested, categorizing the scenarios.
Example: users.service.spec.ts
| Category | Scenario | Expected Behavior | Status |
|---|---|---|---|
| Happy Path | findById with valid ID |
Returns user object | ✅ |
| Error Path | findById with missing ID |
Throws NotFoundException |
✅ |
| Edge Case | findById with SQL injection string |
Handled safely/Not found | ✅ |
3. Verification Results Summary
| File Name | Total Cases | Total Success | Total Failure |
|---|---|---|---|
users.service.spec.ts |
12 | 12 | 0 |
users.controller.spec.ts |
8 | 8 | 0 |
4. Code Coverage
| Metric | Covered / Total | Percentage |
|---|---|---|
| Statements | 180/200 | 90% |
| Branches | 45/50 | 90% |
| Functions | 18/20 | 90% |
| Lines | 160/180 | 88.8% |
[!IMPORTANT] Failure to provide the output in this specific format and export the file is considered a failure to follow the skill set.