Testing - JUnit 5 and Mockito
Learn unit testing in Java with JUnit 5 and Mockito, including mocks, stubs, and clean test structure.
#java #testing #junit5 #mockito
Why this step matters
Reliable software requires tests that are fast, deterministic, and meaningful. Unit tests are your first safety net for refactoring.
Unit test scope
A unit test validates one class behavior in isolation. External dependencies are replaced by test doubles.
JUnit 5 basics
class PriceServiceTest {
@Test
void should_apply_discount_for_premium_user() {
PriceService service = new PriceService();
int result = service.applyDiscount(100, true);
assertEquals(80, result);
}
}
Good test names describe expected behavior.
Mockito: mocks and stubs
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
UserRepository userRepository;
@InjectMocks
UserService userService;
@Test
void should_return_user_when_found() {
when(userRepository.findById(1L)).thenReturn(Optional.of(new User(1L, "briac")));
UserDto dto = userService.findById(1L);
assertEquals("briac", dto.username());
}
}
- stubbing:
when(...).thenReturn(...) - verification:
verify(...)
Test structure suggestion
Use Arrange / Act / Assert:
- prepare inputs and stubs
- execute target method
- assert result and interactions
Common mistakes
- over-mocking everything
- asserting implementation details instead of behavior
- brittle tests coupled to internal refactoring
- naming tests too vaguely
Takeaway
- Keep unit tests fast and isolated
- Use Mockito only for real external dependencies
- Name tests by behavior
- Prefer clear Arrange/Act/Assert structure