CodeGym /Kurse /Spring Test /PostgreSQL über @ServiceConnection

PostgreSQL über @ServiceConnection

Spring Test
Level 25, Lektion 1
Verfügbar

1. Preferred-Pfad und @ServiceConnection

Wenn ein Entwickler zum ersten Mal „Testcontainers“ hört, hat er oft einen Plan auf dem Niveau von „Ich schreibe jetzt 40 Zeilen Konfiguration und besiege die Infrastruktur“. Es funktioniert, aber meistens führt das zu Copy-Paste, undurchsichtigen Property Overrides und Tests, die man nach ein paar Wochen schwer erklären kann. Der Preferred-Pfad in Boot 4 ist dagegen: minimaler manueller Aufwand und maximaler lesbarer Sinn.

Wenn klar ist, dass das Risiko tatsächlich bei PostgreSQL liegt, ist das nächste Problem gar nicht philosophisch: Wie schließt man den Container so an, dass der Test nicht zu einem Lagerhaus manueller spring.datasource.* wird. Für das Standard-Datasource-Szenario wünscht man sich einen kürzeren Weg, und hier entfernt @ServiceConnection genau das überflüssige Plumbing.

Die Idee von @ServiceConnection ist sehr einfach (und deshalb großartig): Sie sagen zu Spring Boot „Hier ist der Container, das ist meine Testdatenbank“, und Boot extrahiert selbst die Verbindungsparameter aus dem Container und setzt sie in die Umgebung ein. Das heißt, Sie hören auf, die Person zu sein, die manuell die JDBC-URL durch den Test schleppt, und werden zur Person, die Tests schreibt. Das ist, seltsamerweise, eher wie das Leben.

Um es in einem Satz zu sagen: @ServiceConnection ist ein in Spring Boot eingebauter „Adapter“ Container → Verbindungseinstellungen, der Ihnen sowohl Zeit als auch die Anzahl der Fehlerquellen spart. Und Fehler in Tests mögen wir aus dem gleichen Grund nicht, aus dem wir Bugs in Production nicht mögen: Sie verderben die Stimmung, und Stimmung ist ein wichtiger Teil der Ingenieursarbeit.

Minimale Abhängigkeiten für Testcontainers

Bevor wir den Container elegant mit einer Annotation verbinden, müssen wir eine banale Sache tun: dass das Projekt überhaupt die Testcontainers-Klassen und die Integration von Spring Boot mit Containern hat. Das ist der Moment, in dem ein Anfänger oft sagt „Aber ich habe doch schon spring-boot-starter-test“, und sich dann wundert, dass PostgreSQLContainer nicht importiert wird. Der Starter ist gut, aber kein Gedankenleser.

In ContentHub haben wir die grundlegende Idee: Testcontainers ist eine Test-Only-Abhängigkeit, und wir brauchen ein „doppeltes“ Set: Testcontainers selbst (und das PostgreSQL-Modul), plus spring-boot-testcontainers, damit Boot @ServiceConnection versteht und den Container automatisch mit der Auto-Konfiguration des Datasource verknüpfen kann.

Beispiel für build.gradle.kts, bewusst kurz und „ohne Magie“::

dependencies {
    testImplementation("org.springframework.boot:spring-boot-starter-test") // JUnit 6, Spring Test, AssertJ usw.
    testImplementation("org.springframework.boot:spring-boot-testcontainers") // Unterstützung für @ServiceConnection in Tests
    testImplementation("org.testcontainers:junit-jupiter") // Integration von Testcontainers mit JUnit 6 (Jupiter API)
    testImplementation("org.testcontainers:postgresql") // PostgreSQLContainer und PostgreSQL-Spezifika
}

Beachten Sie einen wichtigen Punkt: Die Versionen im Kurs werden durch den Boot-Stack festgelegt (wir bauen keinen „Zoo“ manuell zusammen), daher schreiben Sie in einem realen Projekt meistens entweder gar keine Versionen oder nur dort, wo Ihr Dependency Management die benötigte Version nicht aufgreift. Im Übungsprojekt halten wir dies konsistent über den gemeinsamen Platform-Stack des Kurses – und genau das macht diese Integration reproduzierbar.

3. Field-basierter Container in @DataJpaTest

Das direkteste Szenario für ContentHub sind Repository-Tests, die wir bewusst gegen echtes PostgreSQL laufen lassen. Und hier möchte man, dass der Test so zu lesen ist: „Das ist ein @DataJpaTest, aber der Datasource kommt aus dem Container“. Der Field-based-Stil macht das maximal deutlich: Der Container liegt direkt im Testklasse als Feld, und JUnit steuert seinen Lebenszyklus.

Der Hauptvorteil dieser Variante ist, dass Sie auf einen Blick verstehen, wo die Testinfrastruktur versteckt ist, und nicht durch Konfigurationsklassen rennen. Der Nachteil ist auch ehrlich: Wenn Sie anfangen, dieses Feld in 10 Tests zu kopieren, wird sich die Infrastruktur ausbreiten. Deshalb zeigen wir in dieser Lektion sowohl die „geradlinige“ Variante als auch die wiederverwendbare mit @TestConfiguration (etwas später).

Skelett ArticleRepositoryPostgresContainerTest

Beginnen wir mit dem, was man normalerweise zuerst machen möchte: den Container starten und sicherstellen, dass der Spring Data JPA Test auf einer echten Datenbank läuft.

import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers // Testcontainers-Erweiterung verwaltet Container, die mit @Container markiert sind
@DataJpaTest // Slice-Test: hebt die JPA-Schicht (EntityManager, Repositories usw.) hoch
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // DataSource nicht durch embedded ersetzen
class ArticleRepositoryPostgresContainerTest {

    @Container // dieser Container wird von Testcontainers gestartet/gestoppt
    @ServiceConnection // Boot entnimmt url/user/password und konfiguriert DataSource automatisch
    static PostgreSQLContainer
   postgres =
            new PostgreSQLContainer<>("postgres:16-alpine"); // PostgreSQL-Image für Tests
}

Hier gibt es mehrere bedeutungsvolle Dinge, die man besprechen sollte, sonst wirkt es wie „rituelle Annotationen“.

@Testcontainers bindet die JUnit-Erweiterung von Testcontainers ein, die weiß, wie man mit @Container markierte Container startet und stoppt. Die Annotation @Container sagt: „Dieses spezielle Containerobjekt soll gestartet werden“. Und @ServiceConnection – der Schlüssel dieser Lektion – sagt Spring Boot: „Verwende diesen Container als Quelle für die Verbindungsparameter“.

Und ja, mit diesem Skelett kann der Test bereits starten, Migrationen ausführen, den EntityManager hochfahren und für Repository-Überprüfungen bereit sein. Das ist ein Fall von „Magie“ im guten Sinne: weniger manuelle Konfiguration – weniger manuelle Fehler.

static-Container

Wenn Sie den Container nicht als static deklarieren, wird er für jede Instanz der Testklasse erstellt (und potenziell gestartet). Und eine Instanz der Testklasse wird in JUnit 6 normalerweise pro Testmethode erstellt. Ergebnis: Der Container führt ein Leben wie Mayonnaise im Kühlschrank – „mal ist er da, mal nicht, und warum dauert alles so lange“.

Indem Sie den Container als static deklarieren, sagen Sie: „Container ist eine Ressource auf Klassenebene“. JUnit startet ihn einmal pro Klasse und stoppt ihn danach. Das senkt die Startkosten der Tests (innerhalb einer Klasse) drastisch und macht das Verhalten vorhersagbarer.

Um den Effekt zu spüren, stellen Sie sich den Unterschied vor zwischen „einmal PostgreSQL hochfahren und 10 Tests laufen lassen“ und „PostgreSQL 10 Mal hochfahren“. Im zweiten Fall testen Sie nicht die Anwendung – Sie testen die Geduld des Entwicklers. Und wie die Praxis zeigt, bestehen die Geduld der Entwickler Flyway-Migrationen nicht so munter wie PostgreSQL.

@AutoConfigureTestDatabase(replace = NONE)

@DataJpaTest hat eine wichtige Besonderheit: Standardmäßig ersetzt Spring Boot gerne den Datasource durch eine embedded-Variante (falls sie in den Abhängigkeiten verfügbar ist), weil das für viele Projekte der schnellste Weg ist. Aber bei einem Container-Test wollen wir genau nicht ersetzen, sondern ehrlich PostgreSQL aus dem Container verwenden.

Deshalb steht @AutoConfigureTestDatabase(replace = NONE) hier nicht „für die Schönheit“, sondern um Boot zu sagen: „Greif nicht mit deiner Freundlichkeit ein, der Datasource ist bereits gewählt“. Man kann es als Schild „Nicht stören, ich arbeite“ an der Tür betrachten, nur in Form einer Annotation.

4. Wie Boot @ServiceConnection verarbeitet

Um @ServiceConnection nicht wie einen magischen Zauberspruch aus dem Buch „Spring für die Mutigen“ zu behandeln, ist es nützlich, ein einfaches Modell des Geschehens im Kopf zu haben. Wir graben nicht in Boots Innerem (sonst hätten wir einen Kurs „Wie man Boot-Code liest“), aber wir brauchen das Ursache-Wirkungs-Verständnis: warum es funktioniert und warum es kürzer ist als manuelle Eigenschaften.

Im Fall von PostgreSQL startet der Container, bekommt einen dynamischen Port und erzeugt eine JDBC-URL der Form jdbc:postgresql://localhost:54321/.... Der Port kann jedes Mal anders sein (das ist normal), daher kann man die URL nicht fest in der application-test.yml hinterlegen. Dann sieht Spring Boot die Annotation @ServiceConnection und registriert automatisch die Verbindungsdetails in der Umgebung der Anwendung. Und dann macht die normale Auto-Konfiguration des Datasource das, was sie am besten kann: einen DataSource erstellen, der diese Details verwendet.

Man kann es sich so vorstellen:

flowchart TD
    A[JUnit + Testcontainers] --> B[Startet PostgreSQLContainer]
    B --> C[Container liefert JDBC URL / user / password]
    C --> D["@ServiceConnection: Boot übernimmt Verbindungsdetails"]
    D --> E[AutoConfiguration erstellt DataSource]
    E --> F[Flyway/JPA arbeiten mit echtem PostgreSQL]
    F --> G[Test führt Szenario durch und prüft DB-Zustand]

Das wichtigste Gefühl, das Sie mitnehmen sollten: @ServiceConnection ist, als ob Spring Boot selbst den Code geschrieben hätte, den Sie in @DynamicPropertySource schreiben würden, aber es macht das kürzer, einheitlicher und mit weniger Stellen für „Ups, ich habe das Passwort vergessen“.

Und ja, genau deshalb ist @ServiceConnection der Preferred-Pfad. Es macht dasselbe wie die manuelle Registrierung von Eigenschaften, ist aber meist schneller zu schreiben, einfacher zu lesen und besser wartbar. Und in der nächsten Lektion werden wir sehen, was zu tun ist, wenn der automatische Weg aus irgendeinem Grund nicht ausreicht – aber vorerst bleiben wir in der Welt der einfachen Erfolge.

5. Full-Context: @SpringBootTest und Container

Es ist sehr nützlich zu sehen, dass derselbe Weg des Container-Wirings nicht nur für @DataJpaTest funktioniert, sondern auch für den vollständigen Kontext. Denn der Container ist keine „Annotation für Repositories“, sondern einfach eine Möglichkeit, der Anwendung eine echte Datenbank im Test zu geben. Und welche Testebene Sie gewählt haben (Slice oder Full-Context) – das ist eine separate ingenieurtechnische Achse.

Die Form des Tests ist hier anders, die Art der Datenbankverbindung ist dieselbe. Wenn ein bestimmtes Risiko nicht auf Repository-Ebene nachgewiesen werden kann, wandert derselbe Container problemlos in @SpringBootTest.

Im Kurs halten wir stets den Gedanken fest: Der Container ist ein teures Werkzeug, daher setzen wir ihn gezielt ein. Aber wenn Sie entscheiden, dass ein bestimmtes durchgängiges Szenario genau auf PostgreSQL getestet werden muss (z. B. weil Migrationen, Timestamps oder Datenbank-Beschränkungen wichtig sind), dann sind @SpringBootTest + Container durchaus angemessen – nur sollten es wenige sein.

Skelett ArticlePublicationFlowPostgresIntegrationTest

Hier ist ein minimales Gerüst eines Full-Context-Tests, bei dem der Container auf demselben Preferred-Pfad angebunden ist.

import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers // Testcontainers-Erweiterung verwaltet den Lebenszyklus der Container
@SpringBootTest // Full-Context: der gesamte ApplicationContext wird hochgefahren
@AutoConfigureMockMvc // wenn wir über MockMvc gehen, ist es bereits im Kontext
class ArticlePublicationFlowPostgresIntegrationTest {

    @Container // Container startet vor dem Hochfahren des Kontexts und stoppt nach den Tests der Klasse
    @ServiceConnection // Boot setzt die Verbindungseigenschaften zur DB aus dem Container automatisch ein
    static PostgreSQLContainer
   postgres =
            new PostgreSQLContainer<>("postgres:16-alpine"); // PostgreSQL für Integrationstests
}

Es sieht fast verdächtig einfach aus, aber der Sinn ist: Spring Boot startet den vollständigen ApplicationContext, der Datasource stammt aus dem Container, Migrationen werden ausgeführt, JPA ist bereit, und Sie können entweder direkt die Services aufrufen (wenn der Test nicht HTTP betrifft) oder über MockMvc/RestTestClient gehen – je nach gewähltem Integrationsmodus.

Wenn Sie @AutoConfigureMockMvc hinzufügen, können Sie die Kette controller → service → repository durchlaufen, und das ist bereits ein vollwertiger Cross-Layer-Test mit echter Datenbank. Er ist teuer. Deshalb machen wir das bewusst und nicht einfach „weil wir es können“.

Wie man einen Integrationstest nicht auf „Status 200“ reduziert

Ein sehr typisches Problem bei Integrationstests mit echter Datenbank klingt so: „Wir haben den Container gestartet, einen Test geschrieben, und er prüft status().isOk()“. Formal ist der Test grün, aber tatsächlich prüft er so gut wie nichts: Der Container macht den Test nicht nützlicher, wenn Sie nicht den beobachtbaren Effekt prüfen, für den er überhaupt benötigt wurde.

Beispiel (vereinfacht), bei dem wir nicht nur einen HTTP-Request machen, sondern auch den Zustand aus dem Repository zurücklesen:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.MockMvc;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

// Fragment innerhalb von ArticlePublicationFlowPostgresIntegrationTest
@Autowired
MockMvc mockMvc;

@Autowired
ArticleRepository articleRepository;

@Test
void approvePersistsPublishedStatus() throws Exception {
    mockMvc.perform(post("/api/admin/articles/{id}/approve", 42L))
            .andExpect(status().isOk()); // HTTP-Ebene: Anfrage erfolgreich

    // DB-Ebene: Prüfen des beobachtbaren Effekts in der Persistenz
    assertThat(articleRepository.findById(42L).orElseThrow().getStatus())
            .isEqualTo(ArticleStatus.PUBLISHED);
}

Ja, hier gibt es zwei Sätze von Assertions: auf HTTP-Ebene (Status) und auf DB-Ebene (Status des Artikels). Und das ist normal, denn dieser Test ist seinem Sinne nach durchgängig. Er soll beweisen, dass die Anfrage durch die Anwendung gelaufen ist und eine korrekte Spur in der Persistenz hinterlassen hat.

Beachten Sie: Wir prüfen nicht „welche Repository-Methoden aufgerufen wurden“ (das wäre Interaktionstest), und wir prüfen nicht „welches SQL generiert wurde“ (das ist eine andere Art von Aufgaben). Wir prüfen das Verhalten: Nach approve ist der Artikel PUBLISHED. Das ist die Ebene der „Wahrheit“, die in Regression tatsächlich benötigt wird.

6. Bean-basiert: Container in @TestConfiguration

Die Field-basierte Methode ist sehr anschaulich, aber sie hat ein offensichtliches Problem: Wenn Sie mehrere container-gestützte Testklassen haben, beginnen Sie, denselben Codeblock mit static PostgreSQLContainer zu kopieren. Irgendwann ändert jemand die Image-Version an einer Stelle und vergisst es an einer anderen – und Sie bekommen eine „lustige“ Situation: Ein Teil der Tests läuft auf PostgreSQL 16, ein anderer auf PostgreSQL 17. Und das nicht, weil Sie es so wollten, sondern weil Copy-Paste kein Verantwortungsbewusstsein hat.

Die Bean-basierte Variante löst das so: Der Container wird als Test-Only-Bean in einer @TestConfiguration beschrieben, und dann binden Sie ihn dort ein, wo er benötigt wird. Das wird sauberer, und die Wiederverwendung wird kontrollierbar.

Wenn es bereits mehrere container-gestützte Klassen gibt, amortisiert sich eine solche Extraktion recht schnell.

SharedPostgresContainerConfig

Hier ist ein Beispiel einer Test-Only-Konfiguration, die einen PostgreSQL-Container als Bean deklariert und mit @ServiceConnection markiert.

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.testcontainers.containers.PostgreSQLContainer;

@TestConfiguration // wird nur im Testkontext eingebunden
class SharedPostgresContainerConfig {

    @Bean // Container als Spring-Bean verwalten
    @ServiceConnection // Boot entnimmt url/user/password und konfiguriert DataSource
    PostgreSQLContainer
   postgres() {
        // In diesem Stil wird der Lebenszyklus von Spring gesteuert (nicht von JUnit über @Testcontainers/@Container)
        return new PostgreSQLContainer<>("postgres:16-alpine");
    }
}

Der Sinn hier: Spring Boot sieht eine Bean vom Typ PostgreSQLContainer, startet sie (als verwaltete Ressource des Testkontexts) und verwendet automatisch ihre Verbindungsdetails für den Datasource. Sie benötigen kein @Testcontainers und @Container, weil der Lebenszyklus bereits von Spring gesteuert wird, nicht von JUnit.

Dieser Stil ist besonders angenehm, wenn Sie möchten, dass das Container-Setup „eines für eine Gruppe von Tests“ ist und zentral geändert werden kann. Im Übungsprojekt ContentHub ist das durchaus realistisch: Sie haben 2–3 Tests auf PostgreSQL ausgewählt und möchten, dass alle dasselbe Image und dieselbe Container-Konfiguration verwenden.

Einbindung über @Import

Dann importiert der benötigte Test einfach die Konfiguration. Das Ergebnis ist ein Test, der wie ein „normaler @DataJpaTest aussieht, aber mit einer Container-Datenbank.

import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;

@DataJpaTest // Slice-Test für Repositories
@Import(SharedPostgresContainerConfig.class) // Testkonfiguration mit Container einbinden
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) // Boot erlaubt keinen Ersatz des DataSource
class ArticleRepositoryPostgresContainerTest {
    // Hier können Repository-Tests stehen: Container bereits über @Import + @ServiceConnection angebunden
}

Es ist sehr wichtig, nicht „den Container überall einzubinden“. Das wäre der direkte Weg, eine schnelle Test-Suite in eine langsame Maschine zu verwandeln. Daher halten wir solche Imports gezielt: nur die Tests, die wirklich einen echten DB-Pfad verdienen. Und den Klassennamen machen wir ebenfalls ehrlich: ...PostgresContainerTest, damit die Kosten des Tests am Namen erkennbar sind.

7. Wahl zwischen field-basiert vs. bean-basiert

Wenn es beim Testen zwei Wege gibt, dasselbe zu tun, schaltet bei Menschen oft ein innerer „Sektenmodus“ ein: Jemand beginnt, field-basiert zu lieben, jemand bean-basiert. Aber wir brauchen keinen Kult, sondern eine funktionierende ingenieurtechnische Gewohnheit: den Ansatz nach der Aufgabe wählen, nicht nach der Stimmung. Beide Varianten sind normal, sie lösen nur unterschiedliche organisatorische Probleme.

Um die Entscheidung zu erleichtern, hilft es, dies als Vergleich „lokal und explizit“ vs. „zentralisiert und wiederverwendbar“ zu betrachten. Hier ist eine kleine Tabelle, die oft hilft, nicht zu streiten, sondern zu wählen:

Kriterium Field-basiert (@Testcontainers + @Container) Bean-basiert (@TestConfiguration + @Bean)
Wo lebt das Setup Direkt in der Testklasse, maximal explizit Im Config, wird über @Import eingebunden
Wiederverwendung Copy-Paste oder manuelle Abstraktion Natürlich, zentralisiert
„Lesbarkeit auf einen Blick“ Meistens ja Manchmal ein Schritt zum Config nötig
Risiko der Desynchronisation der Image-Version Höher (beim Kopieren) Niedriger (eine Quelle der Wahrheit)
Bequemlichkeit bei wenigen Tests Hervorragend Auch normal, aber etwas mehr „Rahmen“
Bequemlichkeit bei 3+ Container-Tests Beginnt zu nerven Beginnt sich zu lohnen

Wenn Sie sich in der Phase befinden „wir haben genau einen Container-Test, will ihn einfach ausprobieren“, ist die field-basierte Variante meist einfacher und ehrlicher. Wenn Sie bereits eine kleine container-gestützte Teilmenge ausgewählt haben und möchten, dass sie lange und ordentlich lebt, macht die bean-basierte Konfiguration die Suite oft wartbarer.

Und noch ein ingenieurtechnischer Gedanke: Sobald Sie bemerken, dass Sie über Stil streiten, anstatt über Kosten und Lesbarkeit der Tests – ist es Zeit für eine Pause. Normalerweise ist das ein Zeichen, dass Sie vergessen haben, warum Sie überhaupt zum Testen gekommen sind. Wir kamen, um Regressionen zu fangen, nicht um uns an der Anzahl der Annotationen zu messen.

8. Typische Fehler mit @ServiceConnection + PostgreSQL Testcontainers

Fehler Nr. 1: Die Version des PostgreSQL-Images nicht festlegen (oder „schwebend“ festlegen).
Wenn Sie "postgres:16-alpine" schreiben, legen Sie die Major-Version fest, aber Minor/Patch kann „schwimmen“. Das ist manchmal für ein Übungsprojekt in Ordnung, aber in Arbeitscode sollte man die Version so konkret wie möglich festlegen, damit Tests nicht „von selbst“ ihr Verhalten ändern. Der Container ist ein Werkzeug der Sicherheit, kein Generator von Überraschungen.

Fehler Nr. 2: @AutoConfigureTestDatabase(replace = NONE) in @DataJpaTest vergessen.
Das ist die klassische Falle: Sie sind sicher, dass der Test in den Container geht, aber Boot ersetzt leise den Datasource durch embedded, und Sie testen nicht dort, wo Sie denken. Normalerweise taucht das auf, wenn Sie PostgreSQL-spezifisches Verhalten prüfen und plötzlich „seltsame“ Ergebnisse bekommen. Für @DataJpaTest ist die Regel einfach: Container-Datenbank → replace = NONE.

Fehler Nr. 3: Den Container nicht als static deklarieren und versehentlich PostgreSQL für jede Testmethode starten.
Technisch funktioniert alles. Praktisch warten Sie so lange auf die Tests, dass Sie es sich überlegen, Programmierer zu werden, Barista werden und wieder zurückkommen. Der Container ist eine teure Ressource; wenn er auf Klassenebene lebt, sollte er static sein.

Fehler Nr. 4: @ServiceConnection und manuelle Overrides des Datasource „für alle Fälle“ mischen.
Zum Beispiel @ServiceConnection setzen und dann noch spring.datasource.url irgendwo in einem properties-Attribut oder in application-test.yml angeben. Das Ergebnis ist ein Konfigurations-„Kuchen“, der schwer zu erklären ist: was hat tatsächlich gewonnen und warum. Wenn Sie den Preferred-Pfad gewählt haben, lassen Sie ihn sauber arbeiten. Der manuelle Weg ist nur als bewusste Ausnahme sinnvoll.

Fehler Nr. 5: Den Container starten, aber den DB-Zustand nicht prüfen – bei „HTTP 200“ stehenbleiben.
Ein Container-Test ist teuer, und wenn er nichts beweist, was billige Tests nicht auch beweisen, dann ist das kein „Integrationstest“, sondern „integrationsbezogene Selbstberuhigung“. Prüfen Sie den beobachtbaren Effekt: Einzigartigkeit von slugs, Sortierreihenfolge, tatsächlich geschriebene Timestamps, geänderter Artikelstatus, Versionskonflikte. Sonst brummt der Container nur schön im Hintergrund.

1
Aufgabe
Spring Test, Level 25, Lektion 1
Gesperrt
Field-basierter PostgreSQL-Container über `@ServiceConnection`
Field-basierter PostgreSQL-Container über `@ServiceConnection`
1
Aufgabe
Spring Test, Level 25, Lektion 1
Gesperrt
Bean-based PostgreSQL container über `@TestConfiguration` und `@Import`
Bean-based PostgreSQL container über `@TestConfiguration` und `@Import`
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION