Discover how simple tests can save hours of debugging and frustration!
Why Unit testing controllers in NestJS? - Purpose & Use Cases
Imagine manually checking every controller method in your NestJS app by calling APIs and watching logs to see if they work correctly.
This manual testing is slow, easy to forget steps, and you might miss bugs that only happen in rare cases or when data changes.
Unit testing controllers lets you write small automated tests that quickly check if each controller method behaves as expected, catching bugs early and saving time.
Call API manually and check console logs for results
it('should return expected data', () => { expect(controller.method()).toEqual(expected); });Automated, fast, and reliable checks of controller logic that run anytime you change code.
Before deploying a new feature, you run unit tests on controllers to ensure they handle requests correctly without breaking existing functionality.
Manual testing is slow and error-prone.
Unit tests automate checking controller behavior.
They help catch bugs early and improve code confidence.
Practice
Solution
Step 1: Understand the role of a controller
Controllers handle incoming requests and return responses, so testing them focuses on this behavior.Step 2: Identify what unit testing isolates
Unit testing isolates the controller from other parts like services or databases to test its logic alone.Final Answer:
To verify the controller handles requests correctly without depending on other parts -> Option AQuick Check:
Unit testing controller logic = To verify the controller handles requests correctly without depending on other parts [OK]
- Confusing unit tests with integration tests
- Testing database or UI in controller unit tests
- Ignoring mocking dependencies
Solution
Step 1: Recall NestJS testing syntax
Use Test.createTestingModule with a config object specifying controllers or providers, then compile it.Step 2: Identify correct property for controllers
The property to register controllers is 'controllers', not 'services' or 'providers' for controllers.Final Answer:
const module = await Test.createTestingModule({ controllers: [MyController] }).compile(); -> Option CQuick Check:
Use controllers array in createTestingModule = const module = await Test.createTestingModule({ controllers: [MyController] }).compile(); [OK]
- Using 'services' instead of 'controllers' key
- Forgetting to await compile()
- Using new Module() instead of Test.createTestingModule
result be?class MyController {
getHello() {
return 'Hello World!';
}
}
// Test snippet
const controller = new MyController();
const result = controller.getHello();Solution
Step 1: Analyze the controller method
The method getHello returns the string 'Hello World!' synchronously.Step 2: Check the test call
Calling getHello() directly returns the string without errors or async behavior.Final Answer:
'Hello World!' -> Option DQuick Check:
Direct method call returns string = 'Hello World!' [OK]
- Assuming async behavior without async keyword
- Expecting undefined if not mocked
- Confusing method call with property access
describe('MyController', () => {
let controller: MyController;
beforeEach(() => {
controller = new MyController();
});
it('should return greeting', () => {
expect(controller.getHello()).toBe('Hello World!');
});
});Solution
Step 1: Check controller instantiation
Creating controller directly is allowed but only if it has no dependencies.Step 2: Identify missing mocking
If the controller depends on a service, it must be mocked to isolate controller logic.Final Answer:
The test does not mock the service dependency -> Option BQuick Check:
Missing mocks for dependencies = The test does not mock the service dependency [OK]
- Assuming direct instantiation is always wrong
- Forgetting to mock injected services
- Confusing toBe and toEqual for strings
Solution
Step 1: Understand async service method
The service method returns a promise, so the mock must simulate a resolved promise.Step 2: Use jest.fn().mockResolvedValue
This creates a mock that returns a resolved promise with the given value, allowing the controller method to await it.Step 3: Await controller method in test
The test must await the controller method to handle the async call properly.Final Answer:
Mock the service method with jest.fn().mockResolvedValue(value) and await the controller method in the test -> Option AQuick Check:
Use mockResolvedValue and await async calls = Mock the service method with jest.fn().mockResolvedValue(value) and await the controller method in the test [OK]
- Using mockReturnValue for async methods
- Not awaiting async controller methods
- Testing real service instead of mocking
Ready to prove it?
Pass the test and this pattern moves unknown
