Woche 7, Tag 5 — Integration Testing und Testing-Review für die Prüfung
Ziel
Heute schließt du das Thema Testing für die Spring-Professional-Prüfung ab.
Die Kernfragen:
- Was ist ein Integrationstest?
- Was macht
@SpringBootTest? - Wann solltest du
@SpringBootTestnutzen? - Was ist der Unterschied zwischen
@SpringBootTestund Slice-Tests? - Wie testest du vollständige Web-Flows mit MockMvc?
- Wie testest du mit einem echten HTTP-Port?
- Wie testest du mit Testcontainers?
- Wie funktionieren Transaktionen und Rollback in Tests?
- Welches Testing-Wissen reicht für die Spring-Professional-Prüfung?
- Was sind die wichtigsten Prüfungsfallen?
1. Kurz-Wiederholung aus Woche 7
In Woche 7 hast du gelernt:
- Unit-Tests testen eine Klasse ohne Spring.
@WebMvcTesttestet den MVC-/Controller-Slice.@DataJpaTesttestet den JPA-/Repository-Slice.@SpringBootTestlädt den vollständigen Spring-Boot-Application-Context.- MockMvc testet HTTP-Verhalten ohne echten Server.
TestEntityManagerhilft in JPA-Tests.spring-security-testhilft beim Testen gesicherter Endpoints.- Testcontainers kann echte Infrastruktur für Integrationstests bereitstellen.
Merksatz:
Wähle den kleinsten Test, der das Verhalten beweist.
2. Was ist ein Integrationstest?
Ein Integrationstest prüft, dass mehrere Teile der Anwendung zusammenarbeiten.
Beispiele:
Controller + Service + Repository
Security + Controller + Service
Service + Repository + Datenbank
Application Configuration + Beans
REST API + Datenbank
Anwendung + Mock für externen Service
Ein Unit-Test fragt:
Funktioniert diese Klasse allein?
Ein Integrationstest fragt:
Arbeiten diese Teile zusammen?
Merksatz:
Integrationstests beweisen die Zusammenarbeit zwischen Komponenten.
3. Was ist @SpringBootTest?
@SpringBootTest lädt den Spring-Boot-Application-Context.
Beispiel:
@SpringBootTest
class ApplicationContextTest {
@Test
void contextLoads() {
}
}
Das prüft:
Kann Spring den Application Context starten?
Können Beans erstellt werden?
Können Dependencies injiziert werden?
Ist die Konfiguration gültig?
Funktioniert Auto-Configuration?
Merksatz:
@SpringBootTeststartet den vollständigen Spring-Boot-Context.
4. Warum contextLoads nützlich ist
Ein einfacher Test:
@SpringBootTest
class ApplicationContextTest {
@Test
void contextLoads() {
}
}
Er sieht leer aus, ist aber nicht nutzlos.
Er beweist:
Spring kann die Anwendung starten.
Kein erforderlicher Bean fehlt.
Konfigurationsproperties sind gültig genug.
Bean-Dependencies können verdrahtet werden.
Aber er beweist kein Business-Verhalten.
Merksatz:
contextLoadsprüft den Start, nicht Features.
5. Wann solltest du @SpringBootTest nutzen?
Nutze @SpringBootTest, wenn du brauchst:
vollständigen Application Context
echte Service-Beans
echte Repositories
echte Security-Konfiguration
mehrere Layer zusammen
Application Configuration
Setup für externe Integration
Testcontainers
vollständigen Request-Flow
Nutze es nicht für jeden Test.
Für einfache Service-Logik:
Unit-Test ist besser
Nur für Controller:
@WebMvcTest ist besser
Nur für Repository:
@DataJpaTest ist besser
Merksatz:
Nutze
@SpringBootTestnur, wenn der Test die vollständige App braucht.
6. @SpringBootTest vs. Slice-Tests
| Test | Umfang | Gut für |
|---|---|---|
| Unit-Test | eine Klasse, ohne Spring | Business-Logik |
@WebMvcTest | MVC-Slice | Controller, Validation, JSON |
@DataJpaTest | JPA-Slice | Repositories, Mappings, Queries |
@SpringBootTest | vollständiger App-Context | Integrations-Flow |
Merksatz:
Slice-Tests sind fokussiert.
SpringBootTest ist vollständig.
7. @SpringBootTest mit MockMvc
Für vollständige Web-Integration ohne echten Server:
@SpringBootTest
@AutoConfigureMockMvc
class TaskApiIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
void createsTask() throws Exception {
mockMvc.perform(post("/api/tasks")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"title": "Learn Integration Tests"
}
"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.title").value("Learn Integration Tests"));
}
}
Das kann testen:
Spring-Security-Filter
Controller
Validation
Service
Repository
Datenbank
JSON-Serialisierung
Exception Handling
Merksatz:
@SpringBootTest + MockMvctestet einen vollständigen MVC-Flow ohne echten Server.
8. Beispiel: vollständiger Flow-Test
Feature:
POST /api/tasks erstellt einen Task.
GET /api/tasks/{id} gibt den Task zurück.
Test:
@SpringBootTest
@AutoConfigureMockMvc
class TaskApiIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
void createsAndReadsTask() throws Exception {
MvcResult createResult = mockMvc.perform(post("/api/tasks")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"title": "Integration Task"
}
"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.title").value("Integration Task"))
.andReturn();
String responseBody = createResult.getResponse().getContentAsString();
Long taskId = JsonPath.read(responseBody, "$.id");
mockMvc.perform(get("/api/tasks/{id}", taskId))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(taskId))
.andExpect(jsonPath("$.title").value("Integration Task"));
}
}
Das beweist, dass viele Layer zusammenarbeiten.
Merksatz:
Integrationstests können einen realistischen User-Flow testen.
9. @SpringBootTest Web Environment
@SpringBootTest kann mit verschiedenen Web-Environments laufen.
Gängige Modi:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
Bedeutung:
| Modus | Bedeutung |
|---|---|
MOCK | Mock-Servlet-Environment, kein echter Server |
RANDOM_PORT | startet echten Server auf zufälligem Port |
DEFINED_PORT | startet echten Server auf konfiguriertem Port |
NONE | kein Web-Environment |
Merksatz:
MOCKist üblich mit MockMvc;RANDOM_PORTstartet einen echten Server.
10. Echter HTTP-Test mit Random Port
Beispiel:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class TaskApiRealHttpTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void healthEndpointIsAvailable() {
ResponseEntity<String> response =
restTemplate.getForEntity("/actuator/health", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
}
Das startet einen eingebetteten Server auf einem zufälligen Port.
Nützlich, wenn du testen willst:
echte HTTP-Layer
echtes Server-Verhalten
HTTP-Client-Verhalten
vollständigen Request-/Response-Stack
Merksatz:
Nutze
RANDOM_PORT, wenn du echtes HTTP willst.
11. MockMvc vs. TestRestTemplate
| Tool | Server? | Gut für |
|---|---|---|
| MockMvc | kein echter Server | MVC-Integrationstests |
| TestRestTemplate | echter Server | echte HTTP-Integrationstests |
MockMvc:
mockMvc.perform(get("/api/tasks"))
TestRestTemplate:
restTemplate.getForEntity("/api/tasks", String.class)
Merksatz:
MockMvc ist serverlos; TestRestTemplate nutzt echtes HTTP.
12. Integrationstest mit Datenbank
Ein vollständiger Integrationstest kann nutzen:
Controller
Service
Repository
Datenbank
Beispiel:
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
class TaskIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private TaskRepository taskRepository;
@Test
void createdTaskIsStoredInDatabase() throws Exception {
mockMvc.perform(post("/api/tasks")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"title": "Stored Task"
}
"""))
.andExpect(status().isCreated());
assertThat(taskRepository.existsByTitle("Stored Task")).isTrue();
}
}
Der Test prüft sowohl API-Verhalten als auch Datenbankzustand.
Merksatz:
Vollständige Integrationstests können externe Response und internen Datenbankzustand verifizieren.
13. Test-Transaktionen und Rollback
Spring-Tests können transaktional sein.
Beispiel:
@SpringBootTest
@Transactional
class TaskIntegrationTest {
}
Standardmäßig rollen transaktionale Testmethoden nach dem Test zurück.
Bedeutung:
Test erstellt Daten
Test verifiziert Verhalten
Test endet
Transaktion rollt zurück
Datenbank ist wieder sauber
Merksatz:
Transaktionale Tests rollen üblicherweise nach jedem Test zurück.
14. Wichtige Transaktions-Falle mit MockMvc
Wenn die Testmethode @Transactional ist, der Request aber in einem anderen Thread oder im Real-Server-Modus verarbeitet wird, kann das Rollback-Verhalten anders sein.
Mit MockMvc und Mock-Servlet-Environment ist Rollback meist einfacher.
Mit echtem HTTP und RANDOM_PORT kann die Server-Request-Verarbeitung eine andere Transaktion als die Testmethode nutzen.
Dieses Muster kann also knifflig sein:
@SpringBootTest(webEnvironment = RANDOM_PORT)
@Transactional
class RealHttpTest {
}
Merksatz:
Rollback-Verhalten ist einfacher bei Repository-Tests und MockMvc als bei Real-Server-Tests.
15. Strategien für saubere Datenbank
Bei Integrationstests ist Datenbank-Cleanup wichtig.
Optionen:
Transaktions-Rollback
Daten vor jedem Test löschen
Daten nach jedem Test löschen
frischen Testcontainer nutzen
@Sql-Cleanup-Skripte nutzen
Database-Cleaner-Utility nutzen
Gute Regel:
Jeder Test sollte unabhängig sein.
Merksatz:
Integrationstests brauchen eine klare Datenbank-Cleanup-Strategie.
16. @Sql in Integrationstests
Beispiel:
@SpringBootTest
@AutoConfigureMockMvc
@Sql("/sql/clean.sql")
@Sql("/sql/test-data.sql")
class TaskApiIntegrationTest {
}
Beispiel-Cleanup:
delete from tasks;
delete from clients;
Nützlich, wenn:
Testdaten komplex sind
viele Tests dasselbe Setup brauchen
Datenbank explizit bereinigt werden muss
Merksatz:
@Sqlkann Datenbankzustand für Integrationstests vorbereiten oder bereinigen.
17. Testcontainers für Integrationstests
Testcontainers kann eine echte Datenbank in Docker starten.
Beispiel:
PostgreSQL-Container
Redis-Container
Kafka-Container
RabbitMQ-Container
LocalStack-Container
Warum nützlich?
echtes Infrastruktur-Verhalten
produktionsähnliche Datenbank
isolierte Testumgebung
funktioniert in CI
weniger lokales Setup
Native SQL wird realistisch getestet
Merksatz:
Testcontainers liefert produktionsähnliche Infrastruktur für Tests.
18. PostgreSQL-Testcontainers-Beispiel
Dependencies:
testImplementation("org.testcontainers:junit-jupiter")
testImplementation("org.testcontainers:postgresql")
testImplementation("org.springframework.boot:spring-boot-testcontainers")
Test:
@SpringBootTest
@AutoConfigureMockMvc
@Testcontainers
class TaskApiPostgresIntegrationTest {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16");
@Autowired
private MockMvc mockMvc;
@Test
void createsTaskUsingRealPostgres() throws Exception {
mockMvc.perform(post("/api/tasks")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"title": "Postgres Task"
}
"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.title").value("Postgres Task"));
}
}
Wichtig:
Das braucht Docker.
Merksatz:
Nutze Testcontainers, wenn Datenbank-Realismus wichtig ist.
19. Testcontainers ohne @ServiceConnection
Älterer/manueller Stil:
@SpringBootTest
@Testcontainers
class TaskApiPostgresIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16");
@DynamicPropertySource
static void configureDatasource(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
}
Merksatz:
DynamicPropertySourceverbindet Container-Properties mit Spring.
20. Externe Services testen
Rufe in normalen automatisierten Tests keine echten externen Services auf.
Schlecht:
echte E-Mail senden
echten Payment-Provider aufrufen
in Production-S3 hochladen
echte Third-Party-API aufrufen
Besser:
Client mocken
Fake-Server nutzen
Sandbox-Umgebung vorsichtig nutzen
Testcontainers wo möglich
Merksatz:
Integrationstests sollen realistisch, aber sicher sein.
21. Externe Beans in @SpringBootTest mocken
Beispiel:
@SpringBootTest
class OrderIntegrationTest {
@MockitoBean
private PaymentClient paymentClient;
@Autowired
private OrderService orderService;
@Test
void createsOrderWhenPaymentSucceeds() {
when(paymentClient.charge(any()))
.thenReturn(new PaymentResult("OK"));
orderService.createOrder(...);
verify(paymentClient).charge(any());
}
}
Ältere Projekte nutzen vielleicht:
@MockBean
Merksatz:
In Integrationstests unsichere externe Systeme mocken.
22. Application Properties testen
Konfigurationsproperties:
@ConfigurationProperties(prefix = "app.storage")
public class StorageProperties {
private String bucket;
private int maxFileSizeMb;
// getters and setters
}
Test:
@SpringBootTest(properties = {
"app.storage.bucket=test-bucket",
"app.storage.max-file-size-mb=10"
})
class StoragePropertiesTest {
@Autowired
private StorageProperties properties;
@Test
void bindsStorageProperties() {
assertThat(properties.getBucket()).isEqualTo("test-bucket");
assertThat(properties.getMaxFileSizeMb()).isEqualTo(10);
}
}
Merksatz:
Integrationstests können Configuration Binding verifizieren.
23. Profile testen
Beispiel:
@SpringBootTest
@ActiveProfiles("test")
class ApplicationTest {
}
Das lädt:
application-test.yml
Nützlich für:
Test-Datenbank
deaktiviertes E-Mail-Versenden
Fake-API-URLs
Test-Feature-Flags
kleinere Connection Pools
Merksatz:
Nutze Test-Profile für test-spezifische Konfiguration.
24. Security in Integrationstests testen
Beispiel:
@SpringBootTest
@AutoConfigureMockMvc
class SecurityIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
void anonymousCannotAccessTasks() throws Exception {
mockMvc.perform(get("/api/tasks"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser(authorities = "TASK_READ")
void userWithReadAuthorityCanAccessTasks() throws Exception {
mockMvc.perform(get("/api/tasks"))
.andExpect(status().isOk());
}
}
Das prüft echte Security-Konfiguration plus MVC-Flow.
Merksatz:
Integrationstests können echte Security-Regeln verifizieren.
25. CSRF in Integrationstests testen
Wenn CSRF aktiviert ist:
@Test
@WithMockUser(authorities = "TASK_WRITE")
void postWithoutCsrfIsForbidden() throws Exception {
mockMvc.perform(post("/api/tasks")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"title":"Task A"}
"""))
.andExpect(status().isForbidden());
}
Mit CSRF:
@Test
@WithMockUser(authorities = "TASK_WRITE")
void postWithCsrfIsAllowed() throws Exception {
mockMvc.perform(post("/api/tasks")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content("""
{"title":"Task A"}
"""))
.andExpect(status().isCreated());
}
Merksatz:
Wenn CSRF aktiviert ist, brauchen unsichere Methoden CSRF auch in Integrationstests.
26. JWT-Integration testen
Für Resource-Server-Tests:
@Test
void jwtWithReadScopeCanAccessTasks() throws Exception {
mockMvc.perform(get("/api/tasks")
.with(jwt().authorities(
new SimpleGrantedAuthority("SCOPE_task:read")
)))
.andExpect(status().isOk());
}
Das vermeidet die Erzeugung eines echten JWT.
Es testet:
Spring-Security-Authorization mit gemockter JWT-Authentication
Merksatz:
Nutze
jwt(), um Resource-Server-Authorization-Regeln zu testen.
27. Was reicht für die Spring-Professional-Prüfung?
Für die Prüfung: Konzepte verstehen, nicht jedes Tool-Detail auswendig lernen.
Du solltest wissen:
Unit-Test vs. Integrationstest
Test-Pyramide
Rolle von JUnit
Rolle von AssertJ
Rolle von Mockito
Rolle von @MockBean / @MockitoBean
@SpringBootTest
@WebMvcTest
@DataJpaTest
MockMvc
TestEntityManager
Test-Slices
Test-Profile
Test-Properties
Transaktions-Rollback
@DirtiesContext
Security-Testing-Grundlagen
CSRF in Tests
wann Testcontainers nutzen
Merksatz:
Für die Prüfung: wissen, wann und warum du jeden Testtyp nutzt.
28. Entscheidungstabelle Testing für die Prüfung
| Zu testen | Beste Wahl |
|---|---|
| Reine Business-Logik | Unit-Test |
| Service mit gemocktem Repository | Unit-Test + Mockito |
| Controller Request/Response | @WebMvcTest + MockMvc |
| Validation liefert 400 | @WebMvcTest |
Error-Response von @ControllerAdvice | @WebMvcTest |
| Repository-Query | @DataJpaTest |
| Entity-Relationship-Mapping | @DataJpaTest |
| Datenbank-Constraint | @DataJpaTest + flush() |
| Vollständiger App-Context startet | @SpringBootTest |
| Controller + Service + Repository | @SpringBootTest + MockMvc |
| Echter HTTP-Server | @SpringBootTest(RANDOM_PORT) |
| PostgreSQL-spezifisches SQL | Testcontainers PostgreSQL |
| Security-Endpoint-Regel | MockMvc + spring-security-test |
| Method Security | Spring-Test + @WithMockUser |
Merksatz:
Wähle den kleinsten Test, der das Verhalten beweist.
29. Abschließender Testing-Mock-Exam
Frage 1
Was ist ein Unit-Test?
A. Test einer Klasse ohne Spring B. Test des vollständigen Application Context C. Test nur des Datenbankschemas D. Manueller Test des Production-Servers
Antwort:
A
Frage 2
Was macht @SpringBootTest?
A. Lädt den vollständigen Spring-Boot-Application-Context B. Lädt nur JPA-Repositories C. Lädt nur einen Controller D. Deaktiviert Spring
Antwort:
A
Frage 3
Was testet @WebMvcTest?
A. MVC-/Controller-Slice B. Nur vollständige Datenbank C. Nur Kafka D. Nur Flyway
Antwort:
A
Frage 4
Was testet @DataJpaTest?
A. JPA-Entities und Repositories B. Nur REST-Controller C. Nur Security-Filter D. Nur externe APIs
Antwort:
A
Frage 5
Wofür wird MockMvc genutzt?
A. MVC-Requests ohne echten Server testen B. PostgreSQL starten C. JWT-Signaturen erstellen D. Flyway manuell ausführen
Antwort:
A
Frage 6
Wofür wird TestEntityManager genutzt?
A. Entities in JPA-Tests persistieren, flushen, clearen und finden B. CSS testen C. Mock-HTTP-User erstellen D. REST-Calls ausführen
Antwort:
A
Frage 7
Warum flush() in einem Repository-Test?
A. Um SQL-/Datenbank-Constraint-Ausführung zu erzwingen B. Um Spring Security zu deaktivieren C. Um einen Mock zu erstellen D. Um Webserver zu starten
Antwort:
A
Frage 8
Warum clear() in einem Repository-Test?
A. Um nicht nur aus dem Persistence-Context-Cache zu lesen B. Um den Application Context zu löschen C. Um JPA zu deaktivieren D. Um HTTP-Header zu entfernen
Antwort:
A
Frage 9
Was macht @MockBean oder @MockitoBean?
A. Ersetzt einen Spring-Bean durch einen Mockito-Mock B. Erstellt eine Datenbanktabelle C. Startet einen Docker-Container D. Aktiviert Transaktionen
Antwort:
A
Frage 10
Wofür ist Testcontainers nützlich?
A. Echte Infrastruktur wie PostgreSQL in Docker während Tests B. Nur Java-Methoden mocken C. REST-Controller erstellen D. Tests deaktivieren
Antwort:
A
Frage 11
Was ist das Standard-Rollback-Verhalten für transaktionale Spring-Tests?
A. Standardmäßig Rollback B. Immer standardmäßig Commit C. Application Context löschen D. Repositories deaktivieren
Antwort:
A
Frage 12
Wofür wird @DirtiesContext genutzt?
A. Spring mitteilen, den Test-Context nicht wiederzuverwenden B. Nur Datenbankzeilen bereinigen C. JSON erstellen D. Controller mocken
Antwort:
A
Frage 13
Wann solltest du @SpringBootTest statt @WebMvcTest nutzen?
A. Wenn du mehrere Layer oder den vollständigen App-Context brauchst B. Wenn du nur Request-Validation testest C. Wenn du nur eine reine Java-Methode testest D. Nie
Antwort:
A
Frage 14
Wann solltest du @DataJpaTest nutzen?
A. Um Repository-Queries und Entity-Mappings zu testen B. Um React-Komponenten zu testen C. Um nur Controller-JSON zu testen D. Um externen E-Mail-Provider zu testen
Antwort:
A
Frage 15
Was ist der beste Test für reine Berechnungslogik?
A. Unit-Test
B. @SpringBootTest
C. @DataJpaTest
D. Echter HTTP-Test
Antwort:
A
Frage 16
Was ist der beste Test für Controller-Validation?
A. @WebMvcTest
B. @DataJpaTest
C. Manueller Datenbanktest
D. Nur Testcontainers
Antwort:
A
Frage 17
Was ist der beste Test für eine Custom-Repository-Query?
A. @DataJpaTest
B. Einfacher Unit-Test mit gemocktem Repository
C. CSS-Test
D. Nur Controller-Test
Antwort:
A
Frage 18
Was ist der beste Test für vollständigen Controller-Service-Repository-Flow?
A. @SpringBootTest
B. Nur einfacher Unit-Test
C. Nur @JsonTest
D. Kein Test
Antwort:
A
Frage 19
Was macht .with(csrf())?
A. Fügt CSRF-Token zum MockMvc-Request hinzu B. Fügt JWT-Claim hinzu C. Startet Datenbank D. Deaktiviert Validation
Antwort:
A
Frage 20
Was macht @WithMockUser?
A. Fügt gemockten authentifizierten User zum Security-Context hinzu B. Erstellt echten Datenbank-User C. Startet echten Browser D. Deaktiviert Security
Antwort:
A
30. Abschließende Prüfungsfallen
Falle 1
Nutze nicht @SpringBootTest für jeden Test.
Nutze kleinere Tests, wenn möglich.
Falle 2
@WebMvcTest testet kein echtes Service-/Datenbank-Verhalten.
Es testet den Web-Layer.
Falle 3
@DataJpaTest testet keine Controller.
Es testet JPA.
Falle 4
Ein gemocktes Repository beweist nicht, dass Repository-SQL funktioniert.
Es hilft nur beim Testen der Service-Logik.
Falle 5
@MockBean / @MockitoBean ist für Spring-Tests.
Einfache Unit-Tests nutzen Mockito mock() oder @Mock.
Falle 6
POST-/PUT-/PATCH-/DELETE-Tests brauchen vielleicht CSRF.
Falle 7
Validation braucht @Valid.
Falle 8
Repository-Constraint-Tests brauchen oft flush().
Falle 9
Repository-Tests brauchen vielleicht clear(), um gecachte Entities zu vermeiden.
Falle 10
H2 ist nicht immer dasselbe wie PostgreSQL.
Falle 11
Testcontainers ist nützlich, wenn Datenbank-Realismus wichtig ist.
Falle 12
@DirtiesContext kann die Test-Suite verlangsamen.
Falle 13
Integrationstests brauchen eine Cleanup-Strategie.
Falle 14
Rufe in automatisierten Tests keine echten externen Production-Services auf.
Falle 15
Wähle den kleinsten Test, der das Verhalten beweist.
31. Abschließende Testing-Checkliste für die Spring-Professional-Prüfung
Du bist bereit für Testing-Fragen, wenn du erklären kannst:
[ ] Was ein Unit-Test ist.
[ ] Warum Unit-Tests Spring nicht starten sollten.
[ ] Was JUnit macht.
[ ] Was AssertJ macht.
[ ] Was Mockito macht.
[ ] Was Mocks und Stubs sind.
[ ] Was @MockBean / @MockitoBean macht.
[ ] Was @SpringBootTest macht.
[ ] Was @WebMvcTest macht.
[ ] Was @DataJpaTest macht.
[ ] Was MockMvc macht.
[ ] Was TestEntityManager macht.
[ ] Warum flush() nützlich ist.
[ ] Warum clear() nützlich ist.
[ ] Was Test-Slices sind.
[ ] Wann Slice-Tests nutzen.
[ ] Wann vollständige Integrationstests nutzen.
[ ] Was Test-Profile sind.
[ ] Was Test-Properties sind.
[ ] Was @DirtiesContext macht.
[ ] Wie transaktionaler Rollback in Tests funktioniert.
[ ] Wie man Controller-Validation testet.
[ ] Wie man Repository-Queries testet.
[ ] Wie man gesicherte Endpoints testet.
[ ] Warum POST-Tests csrf() brauchen können.
[ ] Was Testcontainers ist.
[ ] Warum H2 sich von PostgreSQL unterscheiden kann.
[ ] Warum Tests unabhängig sein sollten.
[ ] Warum Tests deterministisch sein sollten.
[ ] Wie man den kleinsten nützlichen Test wählt.
32. Abschließende Zusammenfassung
Testing in Spring Boot hat mehrere Ebenen.
Die Hauptebenen sind:
Unit-Tests
Web-Slice-Tests
JPA-Slice-Tests
Integrationstests
Die Hauptregel ist:
Wähle den kleinsten Test, der das Verhalten beweist.
Für Service-Logik:
Nutze Unit-Tests mit JUnit, AssertJ und Mockito.
Für Controller:
Nutze @WebMvcTest und MockMvc.
Für Repositories:
Nutze @DataJpaTest und TestEntityManager.
Für vollständiges Anwendungsverhalten:
Nutze @SpringBootTest.
Für echtes Datenbankverhalten:
Nutze Testcontainers, wenn H2 nicht realistisch genug ist.
Für die Prüfung:
Unit-Test = eine Klasse, ohne Spring.
WebMvcTest = Controller-Slice.
DataJpaTest = Repository-Slice.
SpringBootTest = vollständiger Application Context.
MockMvc = HTTP-ähnlicher MVC-Test ohne echten Server.
Testcontainers = echte Infrastruktur in Docker.
Das reicht als Testing-Wissen für eine solide Spring-Professional-Prüfungsvorbereitung.