CodeGym /Kurse /Spring Test /Erste Web-Slice-Tests für ContentHub

Erste Web-Slice-Tests für ContentHub

Spring Test
Level 9, Lektion 4
Verfügbar

1. Start mit öffentlichen Endpunkten

Wenn Sie jemals versucht haben, direkt mit der Admin-API, Multipart-Upload und einer kniffligen Autorisierung in das Testen von Controllern einzusteigen, kennen Sie diesen Effekt: Es gibt viele Tests, aber das Vertrauen ist null, und es ist unklar, was genau Sie testen. Deshalb ist der Start mit öffentlichen Endpunkten keine „Vereinfachung für Schwächlinge“, sondern eine normale Ingenieursstrategie: Zuerst stabilisieren wir den einfachsten externen Vertrag.

Das JSON-Format des DTO an sich wird separat schneller und präziser geprüft. Die Aufgabe hier ist eine andere: zu sehen, wie Route, Path Variable, Status und JSON-Antwort um den Controller herum zusammengesetzt werden. Daher reicht uns für die ersten Web-Slice-Tests vorerst der grundlegende Rhythmus GET -> status -> ein paar jsonPath, ohne sofort die gesamte HTTP-Mechanik aufzusetzen.

Öffentliche Endpunkte sind gut, weil sie in der Regel read-only sind, minimale Nebenwirkungen haben und die Tests dadurch transparenter werden. Wir streiten nicht über Transaktionen, starten keine Datenbank, denken nicht über Ownership-Regeln nach (wer wessen Entwurf ist). Wir beweisen lediglich: Die URL-Route ist korrekt, der Controller ruft die benötigte Abhängigkeit auf, und nach außen geht ein JSON in der erwarteten Form.

Um die Grenze im Kopf zu behalten, ist es praktisch, sich das MVC-Slice so vorzustellen (vereinfacht, aber sehr nah an der Wahrheit):

flowchart TD
  T["Test method"] -->|"mockMvc.perform(...)"| D["DispatcherServlet"]
  D --> C["PublicArticleController"]
  C --> S["PublicArticleService (mock)"]
  S --> C
  C --> D
  D --> T

Das Schlüsselwort hier ist Mock. Wir „betrügen das System“ nicht, wir sagen ehrlich: „Die Geschäftslogik und die Daten stehen in dieser Schicht nicht im Fokus, wir setzen ihr Ergebnis manuell ein und schauen, wie die Web-Grenze es nach außen weitergibt.“

2. Kontur: Controller, DTO und Mock des Services

Bevor wir einen Test schreiben, ist es sinnvoll, sich buchstäblich eine Minute lang im Kopf zu verankern, was genau wir testen. In unserem Projekt ContentHub sieht der öffentliche Teil der API so aus: eine Liste veröffentlichter Artikel und eine Artikelkarte nach slug. In der echten Anwendung kann der Controller umfangreicher sein, aber für die ersten Tests ist es wichtig, zwei Einstiegspunkte zu sehen.

Hier ist ein vereinfachtes (aber wiedererkennbares) Fragment des Controllers. Nicht, um jetzt Produktionscode zu schreiben, sondern damit die Tests später als „wir prüfen diesen Vertrag“ lesbar sind:

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/public/articles") // Basis-Pfad der öffentlichen API der Artikel
class PublicArticleController {

    private final PublicArticleService publicArticleService;

    PublicArticleController(PublicArticleService publicArticleService) {
        // Constructor injection: die Abhängigkeit wird explizit an den Controller übergeben
        this.publicArticleService = publicArticleService;
    }

    @GetMapping // GET /api/public/articles
    PageResponse<ArticleSummaryResponse> listPublished() {
        // Für den Collection-Endpoint gibt der Controller einfach den Page-Wrapper DTO nach außen
        return publicArticleService.listPublishedArticles();
    }

    @GetMapping("/{slug}") // GET /api/public/articles/{slug}
    ArticleDetailsResponse getBySlug(@PathVariable String slug) {
        // Im web-slice interessiert uns: wird der Service korrekt aufgerufen und das DTO zurückgegeben?
        return publicArticleService.getPublishedArticleBySlug(slug);
    }
}

Beachten Sie zwei Dinge. Erstens hält der Controller über Constructor Injection am Service fest (wie vom Projekt gefordert). Zweitens kommuniziert die öffentliche API über DTOs, nicht über JPA-Entitäten – das vereinfacht uns das Leben enorm: Im Web-Test mocken wir den Service und geben das DTO als „fertige Antwort“ zurück.

Da wir bereits eine separate Ebene für JSON-Verträge hatten, haben Sie die DTOs bereits in @JsonTest gesehen. Wir sollten hier nicht „100%“ dieselben Prüfungen wiederholen, aber wir müssen uns zumindest minimal vergewissern, dass der Controller tatsächlich das zurückgibt, was er dem Client verspricht: z. B. dass slug und title zumindest vorhanden sind und nicht versehentlich umbenannt oder versteckt wurden.

Jetzt sind beide grundlegenden öffentlichen Verträge des Controllers sichtbar – Liste und Details. Daher hängt der erste List-Test nicht in der Luft.

3. Grundgerüst: @WebMvcTest und MockMvc

Jetzt bauen wir eine Testklasse, die maximal „nach der Tagesnorm“ ist: Ein Controller – eine Testklasse, Controller-Abhängigkeiten werden über @MockitoBean ersetzt, und mit MVC arbeiten wir über MockMvc. Viele Anfänger erwarten in diesem Moment Magie, aber die Magie ist sehr alltäglich: Spring startet den Web-Teil, und Sie senden über MockMvc eine Anfrage „als ob HTTP“, jedoch ohne Server zu starten.

Beginnen wir mit dem Skelett. Es ist schon für sich allein nützlich: Eine solche Klasse kann erstellt und gestartet werden – und man stellt fest, dass der Kontext läuft.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(PublicArticleController.class) // Heben nur den web-slice um einen Controller an
class PublicArticleControllerWebMvcTest {

    @Autowired
    MockMvc mockMvc; // Führen Anfragen über MockMvc ohne Starten des realen Servers durch

    @MockitoBean
    PublicArticleService publicArticleService; // Ersetzen Service durch Mock: Geschäftslogik nicht im Fokus des web-slice
}

Hier ist die Logik wichtig: PublicArticleService sollte in diesem Test kein echter Spring-Bean sein. Wir brauchen keine Datenbank, keine Repositories, keine Transaktionen. Wir brauchen nur: „Wenn der Service dies sagt, gibt der Controller das nach außen so weiter.“

Vorerst brauchen wir hier nur einen grundlegenden Pfad über MockMvc: GET, status() und ein paar jsonPath. Das reicht, um die Arbeit des Slices um den Controller zu sehen, ohne gleich in Headers, Media Type und Request Body zu versinken.

Manchmal ist es in der öffentlichen API auch wichtig, einen einheitlichen Error Contract zu sehen (z. B. ApiProblem), der normalerweise über @ControllerAdvice gebildet wird. Wenn in einem Szenario der einheitliche Error Contract wichtig ist, sollte man ApiExceptionHandler besser zu einem sichtbaren Teil des Setups machen – daher ist es hier oft bequemer, diesen Advice explizit über @Import einzubinden. Wenn das jeweilige Slice den Advice bereits selbst einbindet, muss man ihn kein zweites Mal importieren.

import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;

@WebMvcTest(PublicArticleController.class)
@Import(ApiExceptionHandler.class) // Advice explizit einbinden, da für diese Tests der error contract wichtig ist
class PublicArticleControllerWebMvcTest {
    // ...
}

Wir verwandeln den Test nicht in einen Full-Context, wir fügen lediglich eine wichtige Web-Komponente punktuell hinzu, die tatsächlich beeinflusst, was der Client sieht.

4. Happy Path: Liste der Artikel

Am besten beginnt man mit dem „direktesten“ Endpunkt: GET /api/public/articles. Selbst wenn es im echten Projekt Paginierung, Sortierung und Filter gibt, sollte der erste Test maximal ruhig sein: ohne Parameter, ohne komplexe Logik, nur die grundlegende Antwortform. Unser Ziel ist es, den Rhythmus eines MVC-Tests zu spüren: stub → perform → assert.

Zuerst skizzieren wir, was der Service zurückgibt. Angenommen, die öffentliche Liste gibt keine „nackte Liste“ zurück, sondern einen Wrapper PageResponse<T> (im Projekt wird er benötigt, um kein rohes Page<T> nach außen zu geben). Im Test ist uns das egal: Wir geben das Objekt zurück und prüfen, dass es wie erwartet serialisiert wird.

Der Test könnte etwa so aussehen:

import org.junit.jupiter.api.Test;

import java.util.List;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(PublicArticleController.class)
class PublicArticleControllerWebMvcTest {

    @Autowired
    MockMvc mockMvc;

    @MockitoBean
    PublicArticleService publicArticleService;

    @Test
    void returnsPublishedArticlesList() throws Exception {
        // Arrange: DTO vorbereiten, das unser Mock des Services "zurückgibt"
        var page = new PageResponse<>(
            List.of(new ArticleSummaryResponse("spring-slice", "Spring Slice")),
            0, 20, 1
        );

        // Stub: Mock-Verhalten des Services (im web-slice ist der Service nicht echt)
        given(publicArticleService.listPublishedArticles())
            .willReturn(page);

        // Act + Assert: HTTP-Anfrage ausführen und Schlüsselfelder der Antwort prüfen
        mockMvc.perform(get("/api/public/articles"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.items[0].slug").value("spring-slice"))
            .andExpect(jsonPath("$.items[0].title").value("Spring Slice"));
    }
}

Ja, dieser Test sieht aus wie „ich habe das DTO von Hand eingelegt und dann geprüft, dass das JSON korrekt ankam“. Und das ist normal: In @WebMvcTest prüfen wir genau die Web-Grenze. Wir beweisen hier nicht, dass der Artikel tatsächlich veröffentlicht ist (das ist Geschäftslogik), wir beweisen nicht, dass die Datenbankabfrage korrekt ist (das ist Data Layer). Wir beweisen: Der Endpunkt existiert, der Controller ruft die Abhängigkeit auf, die Antwort wird serialisiert und enthält die Schlüsselfelder.

Beachten Sie eine wichtige kleine Disziplin. Wir prüfen nicht das gesamte JSON, machen nicht zehn jsonPath hintereinander und vergleichen keine riesigen verschachtelten Strukturen. Für den ersten Test reichen ein paar tragende Felder (load-bearing): slug und title. Wenn sie vorhanden sind, ist die Wahrscheinlichkeit, dass „alles andere zufällig verschwunden ist“, recht gering, und der Test bleibt lesbar.

5. Happy Path: Artikel nach slug

Der zweite grundlegende öffentliche Vertrag ist die Detailkarte eines Artikels nach slug: GET /api/public/articles/{slug}. Die Testidee ist dieselbe: Wir prüfen nicht, wie der Service den Artikel findet, und prüfen keine Sichtbarkeitsregeln. Wir halten lediglich den Web-Vertrag fest: Die Path Variable wird korrekt gebunden, der Controller ruft den Service mit dem richtigen Slug auf, und der Client erhält ein JSON mit den erwarteten Feldern.

Machen wir den Test etwas „lebendiger“ und fügen ein paar Felder hinzu, damit man spürt, dass es sich um einen Details-Endpunkt handelt und nicht um eine Wiederholung der Zusammenfassung.

import org.junit.jupiter.api.Test;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(PublicArticleController.class)
class PublicArticleControllerWebMvcTest {

    @Autowired MockMvc mockMvc;
    @MockitoBean PublicArticleService publicArticleService;

    @Test
    void returnsArticleDetailsBySlug() throws Exception {
        // Stub: Service muss genau den slug erhalten, der in der path variable kam
        given(publicArticleService.getPublishedArticleBySlug("spring-slice"))
            .willReturn(new ArticleDetailsResponse(
                "spring-slice",
                "Spring Slice",
                "Kurze Zusammenfassung",
                "Artikeltext"
            ));

        // Prüfen: Route existiert, slug wird gebunden, DTO wird in erwartete Felder serialisiert
        mockMvc.perform(get("/api/public/articles/spring-slice"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.slug").value("spring-slice"))
            .andExpect(jsonPath("$.title").value("Spring Slice"));
    }
}

Hier bemerken Sie vielleicht einen interessanten psychologischen Moment. Während Sie den Test schreiben, zieht es das Gehirn: „Lass uns auch noch summary, body, category, publishedAt prüfen …“ Aber gerade im Web-Slice am Anfang ist es wichtig, sich selbst im Zaum zu halten. Zu detaillierte Prüfungen verwandeln den Controller-Test in eine „schwache Kopie des JSON-Contract-Tests“, und das ist ein schlechter Tausch: Der Test wird zerbrechlich, und der Wert wächst nicht so stark wie die Anzahl der Zeilen.

Und noch ein nützlicher Gedanke: Selbst wenn die DTOs bereits mit @JsonTest getestet wurden, ist ein Controller-Test dennoch nützlich. Er fängt Routing-Fehler (@RequestMapping), Binden von Path Variablen, falsche Statuscodes, vergessene @ControllerAdvice, unerwartete Filter/Interceptor und allgemein alles, was nur in der Web-Schicht existiert.

6. Negative Case: 404 und ApiProblem

Negative Szenarien sind ein separates großes Thema, aber ganz ohne sie eine öffentliche API zu testen, wäre seltsam: Für den Client ist es wichtig zu verstehen, was passiert, wenn der Artikel nicht existiert. Wir werden hier keine vollständige Matrix von Statuscodes aufbauen und über jeden Grenzfall diskutieren. Ein einziges verständliches Szenario reicht uns: Der Artikel fehlt – der Client erhält einen korrekten 404 mit einem erwarteten Error-Payload.

Nehmen wir an, der Service wirft eine Ausnahme ArticleNotFoundException, und der ApiExceptionHandler (unser @ControllerAdvice) wandelt sie in ein ApiProblem mit errorCode = "ARTICLE_NOT_FOUND" und dem Status 404 um.

Der Test sieht dann so aus:

import org.junit.jupiter.api.Test;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(PublicArticleController.class)
@Import(ApiExceptionHandler.class) // Advice explizit einbinden, da wir hier den error contract prüfen
class PublicArticleControllerWebMvcTest {

    @Autowired MockMvc mockMvc;
    @MockitoBean PublicArticleService publicArticleService;

    @Test
    void returns404WhenArticleNotFound() throws Exception {
        // Stub: Service meldet "nicht gefunden" via Exception (Controller fängt sie nicht selbst)
        given(publicArticleService.getPublishedArticleBySlug("missing"))
            .willThrow(new ArticleNotFoundException("missing"));

        // Prüfen, dass @ControllerAdvice den korrekten HTTP-Status und Payload erzeugt hat
        mockMvc.perform(get("/api/public/articles/missing"))
            .andExpect(status().isNotFound())
            .andExpect(jsonPath("$.errorCode").value("ARTICLE_NOT_FOUND"));
    }
}

Der Sinn dieses Tests ist nicht, den gesamten Error Contract zu prüfen. Der Sinn ist, festzuhalten: Der Client bekommt keine unerwartete HTML-Fehlerseite mit whitelabel, keinen 500 statt einer verständlichen 404, und der Error-Payload entspricht zumindest minimal dem erwarteten Format.

Wenn dieser Test plötzlich fehlschlägt, weil ApiExceptionHandler nicht im Slice gelandet ist, ist das ebenfalls eine nützliche Diagnose. Sie sehen sofort: Der Controller lebt an sich, aber die Web-Infrastruktur zur Fehlerbehandlung ist im Slice nicht angebunden, und daher spiegelt der Testkontext nicht das reale Web-Verhalten wider.

7. Assertions: Stark, aber nicht zerbrechlich

In Controller-Tests gibt es zwei gegensätzliche Extreme, und beide sehen verlockend aus, bis man eine Woche mit ihnen lebt. Das erste Extrem: „Ich prüfe nur den Status 200, und das war’s.“ Das beweist fast nichts: Man kann ein leeres Objekt zurückgeben, man kann ein völlig anderes JSON zurückgeben, man kann das Feld slug vergessen, und der Test bleibt grün.

Das zweite Extrem: „Ich prüfe das gesamte JSON bis zum letzten Komma.“ Das verwandelt den Controller-Test in eine Schneeflocke: Jede kosmetische Refactoring des DTO, jedes Hinzufügen eines Feldes, selbst eine Änderung der Reihenfolge der Eigenschaften in der Serialisierung (ja, das kommt auch vor) – und die Tests fangen an zu „schreien“, obwohl der Vertrag inhaltlich nicht gebrochen ist.

Daher halten wir in den ersten öffentlichen Tests bewusst die HTTP-Prüfungen kurz. Status plus ein paar tragende JSON-Felder bringen bereits Nutzen; Headers, Content-Type, Request Body und detailliertere Body-Assertions haben dann Sinn, wenn die Schichtgrenze selbst nicht mehr mit der Geschäftslogik verwechselt wird.

Eine gesunde Mitte sieht normalerweise so aus: Für jeden Endpunkt wählen Sie einige Schlüsselprüfungen aus, die wirklich Bedeutung haben. Für die Artikelliste sind das normalerweise items und ein Element darin (z. B. slug, title). Für Details sind das slug und title plus eventuell ein „einzigartiges“ Feld der Details-Antwort (z. B. body), aber nur, wenn es für den Client wirklich kritisch ist.

Es ist sehr nützlich, eine einfache Regel im Kopf zu behalten: Wenn Ihre Prüfung eine „Wiederholung dessen ist, was bereits der @JsonTest geprüft hat“, dann machen Sie sie entweder kürzer oder lassen sie ganz weg. Und wenn Ihre Prüfung etwas ist, das an der Web-Grenze auch bei perfekten DTOs kaputtgehen kann, dann ist das ein guter Kandidat für @WebMvcTest.

Um diesen Gedanken zu festigen, kann man die Schichten in einer kleinen Tabelle vergleichen:

Was kaputt ist Wo fängt man es besser Warum
JSON-Feld im DTO umbenannt @JsonTest Schnellstes Feedback, ohne MVC
@RequestMapping oder Pfad defekt @WebMvcTest Nur an der Web-Grenze sichtbar
Service filtert Veröffentlichte falsch Unit/Integration, aber nicht @WebMvcTest Das ist nicht die Verantwortung des Controllers
Repository sortiert falsch @DataJpaTest Das ist bereits Data-Layer-Verhalten

In dieser Vorlesung bleiben wir bewusst in der oberen Zeile der „Web-Grenze“, und das ist normal.

Mini-Refactoring: DTO-Fabriken im Test

Sobald Sie 2–3 Tests geschrieben haben, kommt die Versuchung: „Jetzt mache ich einen universellen Builder, eine Fabrik von Fabriken und ein DSL, damit alles wie ein Gedicht aussieht.“ Das ist eine gefährliche Stelle. Zu clevere Abstraktionen in Tests verstecken oft die Bedeutung. Aber ganz ohne wiederholten Code ist auch schwer: In jedem Test lange DTO-Konstruktoren neu zu schreiben, ist unangenehm und lenkt manchmal vom Wesentlichen ab.

In den ersten Controller-Tests reichen normalerweise ganz kleine Helper-Methoden direkt in der Testklasse. Sie sollten dumm und offensichtlich sein – wie ein guter Toaster: gedrückt, und das Brot wird warm, ohne „Cloud-Integration“.

Zum Beispiel:

private static ArticleSummaryResponse summary(String slug, String title) {
    // Minimaler Helfer: macht Test kürzer, versteckt aber nicht die Bedeutung
    return new ArticleSummaryResponse(slug, title);
}

private static ArticleDetailsResponse details(String slug) {
    // Einfache Factory mit Defaults: praktisch, solange Felder wenige und nicht szenariokritisch sind
    return new ArticleDetailsResponse(slug, "Title", "Summary", "Body");
}

Jetzt werden die Tests visuell kürzer, aber der Sinn geht nicht verloren:

given(publicArticleService.getPublishedArticleBySlug("spring-slice"))
    // Service gibt vorgefertigtes details DTO zurück
    .willReturn(details("spring-slice"));

Wichtige Einschränkung: Wenn Sie bemerken, dass Helper-Methoden anfangen, 10 Parameter zu akzeptieren und ein „magisches Objekt“ zu bauen, dessen Inhalt unklar ist, haben Sie die Grenze bereits überschritten. Für die ersten Web-Slice-Tests ist Einfachheit besser als eine „Test-Architektur auf dem Niveau eines Startups auf dem Höhepunkt der Investitionen“.

8. Typische Fehler in den ersten @WebMvcTest für öffentliche APIs

Die ersten Controller-Tests scheitern normalerweise nicht, weil Spring „kompliziert“ ist, sondern weil wir versehentlich die Slice-Grenze überschreiten oder im Gegenteil zu schwache Prüfungen machen. Das ist normal: Das Gehirn stellt sich noch von „Feature prüfen“ auf „Schicht prüfen“ um. Im Folgenden einige typische Fallstricke, die ich bei Studenten gesehen habe (und, um ehrlich zu sein, ein paar davon habe ich selbst erwischt, als ich jung und naiv war).

Fehler Nr. 1: Versuch, „den Service durch den Controller zu testen“.
Das häufigste Szenario: Sie schreiben @WebMvcTest, stellen dann fest, dass der Service nicht gestartet ist, und fangen an, die Hälfte der Anwendung in den Kontext zu ziehen – Repositories, Konfigurationen, DataSource. Am Ende wird der Test langsam, komplex und hört auf, lokal zu sein. Im Web-Slice muss der Service gemockt werden, und die Geschäftsregeln sollten in Unit- und Integration-Tests leben.

Fehler Nr. 2: Zu detaillierte JSON-Assertions.
Es ist sehr verlockend, das gesamte JSON festzuhalten, besonders wenn Sie gerade gelernt haben, jsonPath zu verwenden. Aber ein solcher Test schlägt bei jeder kosmetischen Änderung des DTOs fehl: Feld hinzugefügt – Test fällt, Datumsformat geändert – Test fällt, Felder umgestellt – Test fällt. Am Anfang ist es besser, 1–3 Schlüsselfelder zu prüfen, die den Vertrag wirklich tragen.

Fehler Nr. 3: Fehlender @ControllerAdvice im Slice und plötzliche „falsche“ Fehler.
Sie erwarten 404 mit ApiProblem, erhalten aber 500 oder einen seltsamen Standard-Fehlerbody. Die Ursache ist oft einfach: Der Exception-Handler ist nicht im Slice gelandet. Die Lösung ist nicht, den „ganzen Kontext zu ziehen“, sondern punktuell den benötigten @ControllerAdvice über @Import einzubinden, damit das Web-Verhalten production-like wird.

Fehler Nr. 4: Mehrere Controller in einer Testklasse mischen.
Das sieht bequem aus – bis zum ersten Fehlschlag. Dann fangen Sie an zu rätseln: „Warum ist der Mock des Admin-Service im Test des öffentlichen Endpunkts fehlgeschlagen?“ – und verstehen, dass Sie sich selbst einen Abhängigkeitsball geschaffen haben. Ein Controller – eine Testklasse macht das Suite langweiliger, aber vorhersagbarer. Und langweilige Tests sind ein Kompliment, wenn man so will.

Fehler Nr. 5: Zu „verrauschte“ Stub-Daten.
Wenn Sie zur Prüfung von slug und title ein DTO mit zwanzig Feldern zusammenbauen, entsteht im Kopf unnötiges Rauschen: Der Test liest sich wie eine „Datenbaugeschichte“ und nicht wie eine „Prüfung des API-Verhaltens“. In solchen Tests sind minimalistische, aber sinnvolle Antworten besser. Wenn Daten wichtig sind, prüfen Sie sie. Wenn nicht, ziehen Sie sie nicht in das Szenario.

1
Aufgabe
Spring Test, Level 9, Lektion 4
Gesperrt
Erster öffentlicher Web-Slice-Test für die Artikelliste
Erster öffentlicher Web-Slice-Test für die Artikelliste
1
Aufgabe
Spring Test, Level 9, Lektion 4
Gesperrt
Artikelkarte nach Slug und 404-Szenario
Artikelkarte nach Slug und 404-Szenario
1
Umfrage/Quiz
WebMvc-Tests, Level 9, Lektion 4
Nicht verfügbar
WebMvc-Tests
Testen von Spring-Controllern
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION