[JAVA] Web-API-Komponententest und Integrationstest mit SpringBoot + Junit5, 4 Muster

Web-API-Komponententest und Integrationstest

Beim Erstellen einer neuen Web-API mit PJ habe ich überprüft, welche Art von Test mit Junit erstellt werden kann. Notieren Sie sich dies.

Inhaltsverzeichnis

Testcode

  1. [Unit Test (Test nach Klasse)](# 1 Unit Test Test nach Klasse)
  2. [Integrationstest 1 (Integration mehrerer Klassen)](# 2 Integrationstest 1 Integration mehrerer Klassen)
  3. [Integrationstest 2 (Integration aller Klassen, lokale Umgebung)](# 3 Integrationstest 2 Integration aller Klassen, lokale Umgebung)
  4. [Integrationstest 3 (Integration aller Klassen, beliebige Umgebung)](# 4 Integrationstest 3 Integration aller Klassen, beliebige Umgebung)

Zu testender Code

1. Unit Test (Test nach Klasse)

Fügen Sie einen Mock mit Mockito ein, ohne von anderen Klassen abhängig zu sein. Das Testen ist möglich, ohne auf die Implementierung anderer Klassen zu warten.

EmployeeControllerSliceTest


import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import com.example.demo.domain.Employee;
import com.example.demo.usecase.GetEmployeeUsecase;
@WebMvcTest(EmployeeController.class)
class EmployeeControllerSliceTest {
    /**Mock, um in das Testziel zu injizieren*/
    @MockBean
    GetEmployeeUsecase mockedUsecase;
    /**Client für Verbindungstest*/
    @Autowired
    private MockMvc mvc;
    @Test
    void testGetOne() throws Exception {
        //Scheinbewegung einstellen
        when(this.mockedUsecase.getEmployee(anyString())).thenReturn(Optional.ofNullable(new Employee("foo", "bar")));
        //Führen Sie den Test aus
        this.mvc.perform(get("/employees/{employeeId}", "123")) //
        .andExpect(status().is(200)) //
        .andExpect(content().json("{\"employeeId\":\"foo\",\"name\":\"bar\"}")); //Verspotten Sie Daten unabhängig von der Abfrage
    }
}

Referenz Auto-configured Spring MVC Tests Mocking and Spying Beans

2. Integrationstest 1 (Integration mehrerer Klassen)

Kann getestet werden, indem die Abhängigkeit von anderen Klassen explizit deklariert wird.

EmployeeControllerSliceAndImportTest


package com.example.demo.presentation;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.web.servlet.MockMvc;
import com.example.demo.infrastructure.TempEmployeeRepositoryImp;
import com.example.demo.usecase.GetEmployeeUsecase;
@WebMvcTest(EmployeeController.class)
@Import({ GetEmployeeUsecase.class, TempEmployeeRepositoryImp.class })
class EmployeeControllerSliceAndImportTest {
    /**Client für Verbindungstest*/
    @Autowired
    private MockMvc mvc;
    @Test
    void testGetOne() throws Exception {
        //Lauf
        this.mvc.perform(get("/employees/{employeeId}", "123")) //
        //Bestätigung
        .andExpect(status().is(200)) //
        .andExpect(content().json("{\"employeeId\":\"123\",\"name\":\"Taro\"}")); //Daten aus dem Repository erhalten
    }
}

Referenz Auto-configured Spring MVC Tests

3. Integrationstest 2 (Integration aller Klassen, lokale Umgebung)

Lokale Tests sind in einer Umgebung möglich, die fast der beim Starten des eigentlichen Servers entspricht.

EmployeeControllerOnLocalhostTest


package com.example.demo.presentation;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpStatus;
import org.springframework.test.web.reactive.server.WebTestClient;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class EmployeeControllerOnLocalhostTest {
    /**Client für Verbindungstest*/
    WebTestClient client = WebTestClient.bindToServer().build();
    /**Verbindungsziel-Portnummer*/
    @LocalServerPort
    private int port;
    @Test
    void test() throws Exception {
        //Lauf
        this.client.get().uri("http://localhost:" + this.port + "/employees/{employeeId}", "123").exchange() //
        //Bestätigung
        .expectStatus().isEqualTo(HttpStatus.valueOf(200)) //
        .expectBody(String.class).isEqualTo("{\"employeeId\":\"123\",\"name\":\"Taro\"}");
    }
}

Referenz Testing with a running server WebTestClient Spring WebClient Requests with Parameters

4. Integrationstest 3 (Integration aller Klassen, jeder Umgebung)

Sie können eine Verbindung zu jedem laufenden Server herstellen und dessen Verhalten testen. Der Server muss separat gestartet werden, bevor der Junit-Test ausgeführt wird. Umgekehrt können Sie jeden laufenden Web-API-Server testen. Es muss nicht Java sein.

EmployeeControllerOnExternalServerTest


package com.example.demo.presentation;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.test.web.reactive.server.WebTestClient;
class EmployeeControllerOnExternalServerTest {
    /**Client für Verbindungstest*/
    WebTestClient client = WebTestClient.bindToServer().build();
    /**Verbindungsziel-Portnummer*/
    private final int port = 8080;
    @Test
    void test() throws Exception {
        //Lauf
        this.client.get().uri("http://localhost:" + this.port + "/employees/{employeeId}", "123").exchange() //
        //Bestätigung
        .expectStatus().isEqualTo(HttpStatus.valueOf(200)) //
        .expectBody(String.class).isEqualTo("{\"employeeId\":\"123\",\"name\":\"Taro\"}");
    }
}

Referenz WebTestClient Spring WebClient Requests with Parameters

Zu testender Code

EmployeeController.java

EmployeeController


package com.example.demo.presentation;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.domain.Employee;
import com.example.demo.usecase.GetEmployeeUsecase;
@RestController
public class EmployeeController {
    @Autowired
    GetEmployeeUsecase getUsecase;
    @GetMapping("/employees/{employeeId}")
    Optional<Employee> getOne(@PathVariable final String employeeId) {
        return this.getUsecase.getEmployee(employeeId);
    }
}

GetEmployeeUsecase.java

GetEmployeeUsecase


package com.example.demo.usecase;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.domain.Employee;
import com.example.demo.domain.EmployeeRepository;
@Service
public class GetEmployeeUsecase {
    @Autowired
    EmployeeRepository repository;
    public Optional<Employee> getEmployee(final String employeeId) {
        return this.repository.findOneById(employeeId);
    }
}

Employee.java

Employee


package com.example.demo.domain;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class Employee {
    private String employeeId = null;
    private String name = null;
    @SuppressWarnings("unused")
    private Employee() {
    }
}

EmployeeRepository.java

EmployeeRepository


package com.example.demo.domain;
import java.util.Optional;
import org.springframework.stereotype.Repository;
public interface EmployeeRepository {
    Optional<Employee> findOneById(String employeeId);
}

TempEmployeeRepositoryImp.java

TempEmployeeRepositoryImp


package com.example.demo.infrastructure;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Repository;
import com.example.demo.domain.Employee;
import com.example.demo.domain.EmployeeRepository;
@Repository
public class TempEmployeeRepositoryImp implements EmployeeRepository {
    private final List<Employee> db;
    public TempEmployeeRepositoryImp() {
        this.db = new ArrayList<>();
        //Als Ausgangsdaten
        this.db.add(new Employee("123", "Taro"));
    }
    @Override
    public Optional<Employee> findOneById(final String employeeId) {
        return this.db.stream().filter(e -> e.getEmployeeId().equals(employeeId)).findFirst();
    }
}

GitHub https://github.com/tmtmra/restControllerTestSample

Schließlich

Ich bin ein Anfänger, der vor einem Jahr mit dem Programmieren begonnen hat. Bitte geben Sie mir verschiedene Meinungen und Ratschläge.

Recommended Posts

Web-API-Komponententest und Integrationstest mit SpringBoot + Junit5, 4 Muster
Machen Sie einen Unit-Test mit Junit.
Mischen Sie Testfälle mit JUnit 5 und Standardmethoden
Integrationstest mit Gradle
Testen Sie die Web-API mit junit
[Java] Testen Sie private Methoden mit JUnit
Kopieren Sie den Test und fügen Sie ihn mit RSpec ein
Testen Sie den Spring Framework Controller mit Junit
[Schienen] Machen wir einen Unit-Test mit Rspec!
Führen Sie RSpec ein und schreiben Sie den Unit-Test-Code
Steuern Sie die Testreihenfolge in Junit4 mit einem Aufzählungstyp
So testen Sie den privaten Bereich mit JUnit
Der JUnit 5-Gradle-Test führt zu einem Fehler mit der Lombok-Annotation
Einführung eines automatisierten Java-Tests mit JUnit 5 + Gradle
[Java] So testen Sie, ob es in JUnit null ist
Informationen zum Entwerfen einer Spring Boot- und Unit-Test-Umgebung
[CircleCI 2.0] [Java] [Maven] [JUnit] Aggregieren Sie die JUnit-Testergebnisse mit CircleCI 2.0
Einführung automatisierter Java-Tests mit JUnit 5 + Apache Maven
So testen Sie Interrupts während Thread.sleep mit JUnit
Erstellen und testen Sie Java + Gradle-Anwendungen mit Wercker
Einfacher JUnit-Test der Elasticsearch 2018-Version mit Embedded-Elasticsearch
Überschreiben Sie den Inhalt der Konfiguration mit Spring-boot + JUnit5
Testcode mit Mock mit JUnit (EasyMock Center)
Machen Sie einen Unit-Test mit Junit.
Web-API-Komponententest und Integrationstest mit SpringBoot + Junit5, 4 Muster
Führen Sie RSpec ein und schreiben Sie den Unit-Test-Code
Steuern Sie die Testreihenfolge in Junit4 mit einem Aufzählungstyp
Informationen zum Entwerfen einer Spring Boot- und Unit-Test-Umgebung
Mischen Sie Testfälle mit JUnit 5 und Standardmethoden
JUnit Teststart versuchen Sie etwas
Java Unit Test Library-Arterien-Probe
Verwenden Sie Spring Test + Mockito + JUnit 4 für Spring Boot + Spring Retry Unit Test