Testy JUnit 5 + Mockito
ProfessNet testuje kod Java w JUnit 5 (Jupiter), z Mockito do mockowania i AssertJ do czytelnych asercji. Ta lekcja pokazuje nasze wzorce — od czystej jednostki po test warstwy webowej Spring Boot.
Anatomia testu JUnit 5
Układ AAA: 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");
}
}
Standard ProfessNet: nazwa metody testowej opisuje zachowanie (
metoda_warunek_wynik). Klasy testowe i metody mają domyślny dostęp (package-private) — w JUnit 5 nie muszą byćpublic.
Testy parametryzowane
@ParameterizedTest
@CsvSource({"CORP, corp", "' Dmz ', dmz", "'', ''"})
void normalize(String input, String expected) {
assertThat(ForestName.normalize(input)).isEqualTo(expected);
}
AssertJ — płynne asercje
assertThat(probes)
.hasSize(2)
.extracting(Probe::host)
.containsExactly("dc01", "dc02");
assertThatThrownBy(() -> service.runScan(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("forest");
Standard ProfessNet: asercje piszemy w AssertJ (
assertThat) — czytelniejsze i z lepszym komunikatem błędu niż suroweassertEquals.
Mockito — izolacja zależności
@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 tworzy atrapę, @InjectMocks wstrzykuje ją do testowanej klasy.
Testy warstwy webowej Spring Boot
@WebMvcTest ładuje tylko warstwę kontrolera (szybko), a zależności mockuje.
@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"));
}
}
| Adnotacja / narzędzie | Do czego |
|---|---|
@Test, @ParameterizedTest | przypadki testowe |
@Mock, @InjectMocks | atrapy i wstrzyknięcie (Mockito) |
assertThat(...) (AssertJ) | czytelne asercje |
@WebMvcTest + MockMvc | test kontrolera bez pełnego kontekstu |
@SpringBootTest | test integracyjny z pełnym kontekstem |
Wskazówka:
@SpringBootTestładuje cały kontekst — jest wolny. Używaj go do testów integracyjnych, a do jednostek wybieraj@WebMvcTest/ czysty Mockito bez Springa.
JUnit 5 + Mockito + AssertJ to nasz standardowy zestaw. Szybkie jednostki na logice serwisów plus kilka testów webowych dają pewność przy każdym PR-ze — i są warunkiem wejścia do głównej gałęzi.