JUnit 5 + Mockito tests
ProfessNet tests Java code with JUnit 5 (Jupiter), with Mockito for mocking and AssertJ for readable assertions. This lesson shows our patterns — from a pure unit to a Spring Boot web-layer test.
Anatomy of a JUnit 5 test
The AAA layout: Arrange, Act, Assert.
class ForestNameTest {
@Test
void normalize_trimsAndLowercases() {
// Arrange
String raw = " CORP.LOCAL ";
// Act
String result = ForestName.normalize(raw);
// Assert
assertThat(result).isEqualTo("corp.local");
}
}
ProfessNet standard: the test method name describes the behavior (
method_condition_result). Test classes and methods have default (package-private) access — in JUnit 5 they need not bepublic.
Parameterized tests
@ParameterizedTest
@CsvSource({"CORP, corp", "' Dmz ', dmz", "'', ''"})
void normalize(String input, String expected) {
assertThat(ForestName.normalize(input)).isEqualTo(expected);
}
AssertJ — fluent assertions
assertThat(probes)
.hasSize(2)
.extracting(Probe::host)
.containsExactly("dc01", "dc02");
assertThatThrownBy(() -> service.runScan(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("forest");
ProfessNet standard: we write assertions with AssertJ (
assertThat) — more readable and with a better error message than rawassertEquals.
Mockito — dependency isolation
@ExtendWith(MockitoExtension.class)
class InventoryServiceTest {
@Mock private ProbeRepository repository;
@InjectMocks private InventoryService service;
@Test
void runScan_returnsResultWithHostCount() {
// Arrange
when(repository.getHosts("corp")).thenReturn(List.of("dc01"));
// Act
ScanResult result = service.runScan("corp");
// Assert
assertThat(result.hostCount()).isEqualTo(1);
verify(repository).getHosts("corp");
}
}
@Mock creates a stub, @InjectMocks injects it into the class under test.
Spring Boot web-layer tests
@WebMvcTest loads only the controller layer (fast) and mocks the
dependencies.
@WebMvcTest(InventoryController.class)
class InventoryControllerTest {
@Autowired private MockMvc mockMvc;
@MockBean private InventoryService service;
@Test
void scan_returns202() throws Exception {
when(service.runScan("corp"))
.thenReturn(new ScanResult("job-1", "corp", Instant.now()));
mockMvc
.perform(post("/api/v1/inventory/scan")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"forest\":\"corp\"}"))
.andExpect(status().isAccepted())
.andExpect(jsonPath("$.jobId").value("job-1"));
}
}
| Annotation / tool | For what |
|---|---|
@Test, @ParameterizedTest | test cases |
@Mock, @InjectMocks | stubs and injection (Mockito) |
assertThat(...) (AssertJ) | readable assertions |
@WebMvcTest + MockMvc | a controller test without the full context |
@SpringBootTest | an integration test with the full context |
Tip:
@SpringBootTestloads the whole context — it's slow. Use it for integration tests, and for units choose@WebMvcTest/ pure Mockito without Spring.
JUnit 5 + Mockito + AssertJ is our standard toolkit. Fast units on service logic plus a few web tests give confidence with every PR — and are an entry condition for the main branch.