RU | EN | DE

1. Arten von Tests

  1. Unit-Tests → überprüfen einzelne Klassen (schnell, isoliert).
  2. Integrationstests → überprüfen die Interaktion von Komponenten (z.B. Service + Datenbank).
  3. End-to-End (E2E) → überprüfen das gesamte API (über MockMvc/TestRestTemplate).

2. Unit-Tests (JUnit 5)

📄 Abhängigkeit (normalerweise bereits in spring-boot-starter-test enthalten):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

📄 Beispiel:

class Calculator {
    int sum(int a, int b) { return a + b; }
}
class CalculatorTest {
    Calculator calc = new Calculator();
    @Test
    void testSum() {
        assertEquals(5, calc.sum(2, 3));
    }
}

3. Mockito (Mocks und Stubs)

📄 Beispiel:

@Service
class UserService {
    private final UserRepository repo;
    public UserService(UserRepository repo) { this.repo = repo; }
    User getById(Long id) { return repo.findById(id).orElseThrow(); }
}
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    @Mock UserRepository repo;
    @InjectMocks UserService service;
    @Test
    void testGetById() {
        User u = new User(); u.setName("Vitaliy");
        when(repo.findById(1L)).thenReturn(Optional.of(u));
        User result = service.getById(1L);
        assertEquals("Vitaliy", result.getName());
    }
}

4. Spring Boot Integration Test

📄 Beispiel:

@SpringBootTest
class UserServiceIntegrationTest {
    @Autowired UserRepository repo;
    @Autowired UserService service;
    @Test
    void testCreateUser() {
        User u = new User();
        u.setName("Test");
        service.createUser(u);
        assertThat(repo.findByName("Test")).isNotEmpty();
    }
}

📌 Die Annotation @SpringBootTest bindet den gesamten Spring-Kontext (langsamer, aber am realitätsnahesten).

5. MockMvc (Testen von REST APIs)

📄 Beispiel:

@WebMvcTest(UserController.class)
class UserControllerTest {
    @Autowired private MockMvc mockMvc;
    @MockBean private UserService service;
    @Test
    void testGetUsers() throws Exception {
        when(service.allUsers()).thenReturn(List.of(new UserDto(1L, "Vitaliy")));
        mockMvc.perform(get("/api/users"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$[0].name").value("Vitaliy"));
    }
}

📌 @WebMvcTest bindet nur die Web-Schicht (ohne Datenbank). 📌 @MockBean ersetzt den Service durch einen Mock.

6. TestRestTemplate (Integrationstests für APIs)

📄 Beispiel:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserApiTest {
    @Autowired TestRestTemplate restTemplate;
    @Test
    void testCreateUser() {
        UserDto dto = new UserDto(null, "Vitaliy");
        ResponseEntity<UserDto> response =
            restTemplate.postForEntity("/api/users", dto, UserDto.class);
        assertEquals(HttpStatus.OK, response.getStatusCode());
        assertEquals("Vitaliy", response.getBody().name());
    }
}

7. Testcontainers (mit echter Datenbank)

📄 Beispiel:

@SpringBootTest
@Testcontainers
class UserRepositoryTest {
    @Container
    static PostgreSQLContainer<?> postgres =
        new PostgreSQLContainer<>("postgres:15")
            .withDatabaseName("demo")
            .withUsername("demo")
            .withPassword("secret");
    @DynamicPropertySource
    static void props(DynamicPropertyRegistry reg) {
        reg.add("spring.datasource.url", postgres::getJdbcUrl);
        reg.add("spring.datasource.username", postgres::getUsername);
        reg.add("spring.datasource.password", postgres::getPassword);
    }
 
    @Autowired UserRepository repo;
    @Test
    void testSaveUser() {
        User u = new User();
        u.setName("Vitaliy");
        repo.save(u);
        assertThat(repo.findByName("Vitaliy")).isNotEmpty();
    }
}

📌 Dies sind die realistischsten Integrationstests.

8. H2 (In-Memory DB)

Schnelle Alternative für Dev/Test. 📄 Konfiguration:

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password: password
  h2:
    console:
      enabled: true

📌 H2-Konsole öffnen: http://localhost:8080/h2-console

9. Test Utilities

  • @DataJpaTest → testet nur die JPA-Schicht.
  • @JsonTest → testet die Serialisierung/Deserialisierung von Jackson.
  • @WebMvcTest → nur Controller.
  • @SpringBootTest → gesamter Kontext.

10. Best Practices

  • ✅ Schreibe Unit-Tests für die Geschäftslogik.
  • ✅ Integrationstests → für Datenbanken und APIs.
  • ✅ Verwende MockMvc für REST, anstatt den gesamten Server zu starten.
  • ✅ Für komplexe Fälle → Testcontainers (echte Datenbank in Docker).
  • ✅ Tests sollten schnell und isoliert sein.
  • ✅ Testlevel:
    • Unit → günstig und schnell,
    • Integration → teurer,
    • E2E → nur für kritische Szenarien.