Services hold business rules, so they deserve focused unit tests. This lesson covers repository mocks, exception assertions, and arranging clear service scenarios.
Service Test Structure
Arrange mocks for repositories and collaborators, act by calling the service method, assert outcomes and interactions. Cover happy paths and intentional failure paths (not found, conflict, validation delegated upstream).
Do not re-test ValidationPipe inside service unit tests—DTO validation belongs to pipe/e2e tests.
When services call other services, mock those collaborators.
Prefer dependency injection tokens that make swapping fakes easy.
Name tests after business behavior, not implementation details.
Service Testing Cheatsheet
High-value assertions for services.
Scenario
Assert
Create
Saved payload + returned entity
Read missing
Throws NotFoundException
Update
Loads, merges, saves
Delete
Calls remove / affected count
Permission deny
Throws ForbiddenException
Testing Transactions
If a service uses transactions, mock the transaction API and assert that rollback occurs when a step fails—or extract a unit that is easier to test and cover transactions in integration tests.
Time and IDs
Inject clocks or id generators when services depend on new Date() or random ids so tests stay deterministic.
Common Mistakes
Only testing happy paths.
Asserting Nest HTTP response objects inside service tests.
Using real databases for every service unit test.
Duplicating the same repository mock setup in every file without helpers.
Key Takeaways
Service tests mock persistence and assert business outcomes.
Cover not-found and conflict paths explicitly.
Leave DTO pipe validation to other test layers.
Keep scenarios named after business behavior.
Pro Tip
For each public service method, write at least one success test and one failure test before marking the feature done—it's a cheap safety net.
You now can test Nest services well. Next, test Controllers specifically.