This skill provides patterns for unit testing @Service classes using Mockito. It covers mocking all injected dependencies, verifying business logic, testing complex workflows, argument capturing, verification patterns, and testing async/reactive services without starting the Spring container.
When to Use
Use this skill when:
Testing business logic in @Service classes
Mocking repository and external client dependencies
Verifying service interactions with mocked collaborators
Testing complex workflows and orchestration logic
Want fast, isolated unit tests (no database, no API calls)
Testing error handling and edge cases in services
Instructions
Follow these steps to test service layer with Mockito:
1. Add Testing Dependencies
Include JUnit 5, Mockito, and AssertJ in your test classpath.
2. Create Test Class with Mockito Extension
Use @ExtendWith(MockitoExtension.class) to enable Mockito annotations.
3. Declare Mocks and Service Under Test
Use @Mock for dependencies and @InjectMocks for the service being tested.
4. Arrange Test Data
Create test data objects and configure mock return values using when().thenReturn().
5. Execute Service Method
Call the service method being tested with test inputs.
6. Assert Results
Verify the returned value using AssertJ assertions and verify mock interactions.
7. Test Exception Scenarios
Configure mocks to throw exceptions and verify error handling.
// Calls real userService methods but userRepository is mocked
}
Constructor Injection for Testing
:
// In your service (production code)
public
class
UserService
{
private
final
UserRepository
userRepository
;
public
UserService
(
UserRepository
userRepository
)
{
this
.
repository
=
userRepository
;
}
}
// In your test - can inject mocks directly
@Test
void
test
(
)
{
UserRepository
mockRepo
=
mock
(
UserRepository
.
class
)
;
UserService
service
=
new
UserService
(
mockRepo
)
;
}
Troubleshooting
UnfinishedStubbingException
Ensure all
when()
calls are completed with
thenReturn()
,
thenThrow()
, or
thenAnswer()
.
UnnecessaryStubbingException
Remove unused stub definitions. Use
@ExtendWith(MockitoExtension.class)
with
MockitoExtension.LENIENT
if you intentionally have unused stubs.
NullPointerException in test
Verify
@InjectMocks
correctly injects all mocked dependencies into the service constructor.
Constraints and Warnings
Do not mock value objects or DTOs; create real instances with test data.
Avoid mocking too many dependencies; consider refactoring if a service has too many collaborators.
Tests should not rely on execution order; each test must be independent.
Be cautious with
@Spy
as it can lead to partial mocking which is harder to understand.
Mock static methods with caution using Mockito-Inline; it can cause memory leaks in long-running test suites.
Do not test private methods directly; test them through public method behavior.
Argument matchers (
any()
,
eq()
) cannot be mixed with actual values in the same stub.
Avoid over-verifying; verify only interactions that are important to the test scenario.
References
Mockito Documentation
JUnit 5 User Guide
AssertJ Assertions