Suche…


So testen Sie eine einfache Spring-Boot-Anwendung

Wir haben ein Beispiel für eine Spring-Boot-Anwendung, die Benutzerdaten in MongoDB speichert, und wir verwenden Rest-Services, um Daten abzurufen

Zunächst gibt es eine Domänenklasse, z. B. POJO

@Document
public class User{
    @Id
    private String id;

    private String name;

}

Ein entsprechendes Repository basierend auf Spring Data MongoDB

public interface UserRepository extends MongoRepository<User, String> {
}

Dann unser User Controller

@RestController
class UserController {
 
    @Autowired
    private UserRepository repository;
 
    @RequestMapping("/users")
    List<User> users() {
        return repository.findAll();
    }
 
    @RequestMapping(value = "/Users/{id}", method = RequestMethod.DELETE)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    void delete(@PathVariable("id") String id) {
        repository.delete(id);
    }
 
    // more controller methods
}

Und zum Schluss noch unsere Spring Boot Applikation

@SpringBootApplication
public class Application {
    public static void main(String args[]){
     SpringApplication.run(Application.class, args);
    }
}

Wenn beispielsweise John Cena, The Rock und TripleHHH die einzigen drei Benutzer in der Datenbank wären, würde eine Anfrage an / Benutzer die folgende Antwort geben:

$ curl localhost:8080/users
[{"name":"John Cena","id":"1"},{"name":"The Rock","id":"2"},{"name":"TripleHHH","id":"3"}]

Um den Code zu testen, überprüfen wir nun, ob die Anwendung funktioniert

@RunWith(SpringJUnit4ClassRunner.class)   // 1
@SpringApplicationConfiguration(classes = Application.class)   // 2
@WebAppConfiguration   // 3
@IntegrationTest("server.port:0")   // 4
public class UserControllerTest {

    @Autowired   // 5
    UserRepository repository;

    User cena;
    User rock;
    User tripleHHH;

    @Value("${local.server.port}")   // 6
    int port;

    @Before
    public void setUp() {
        // 7
        cena = new User("John Cena");
        rock = new User("The Rock");
        tripleHHH = new User("TripleHH");

        // 8
        repository.deleteAll();
        repository.save(Arrays.asList(cena, rock, tripleHHH));

        // 9
        RestAssured.port = port;
    }

    // 10
    @Test
    public void testFetchCena() {
        String cenaId = cena.getId();

        when().
                get("/Users/{id}", cenaId).
        then().
                statusCode(HttpStatus.SC_OK).
                body("name", Matchers.is("John Cena")).
                body("id", Matchers.is(cenaId));
    }

    @Test
    public void testFetchAll() {
        when().
                get("/users").
        then().
                statusCode(HttpStatus.SC_OK).
                body("name", Matchers.hasItems("John Cena", "The Rock", "TripleHHH"));
    }

    @Test
    public void testDeletetripleHHH() {
        String tripleHHHId = tripleHHH.getId();

        when()
                .delete("/Users/{id}", tripleHHHId).
        then().
                statusCode(HttpStatus.SC_NO_CONTENT);
    }
}

Erläuterung

  1. Wie bei jedem anderen Spring-basierten Test benötigen wir den SpringJUnit4ClassRunner damit ein Anwendungskontext erstellt wird.
  2. Die Annotation @SpringApplicationConfiguration ähnelt der Annotation @ContextConfiguration Sie wird verwendet, um anzugeben, welche Anwendungskontexte im Test verwendet werden sollen. Darüber hinaus wird eine Logik zum Lesen von Spring Boot-spezifischen Konfigurationen, Eigenschaften usw. ausgelöst.
  3. @WebAppConfiguration muss vorhanden sein, um Spring mitzuteilen, dass ein WebApplicationContext für den Test geladen werden soll. Außerdem enthält es ein Attribut zum Angeben des Pfads zum Stammverzeichnis der Webanwendung.
  4. @IntegrationTest Spring Boot mit, dass der eingebettete Webserver gestartet werden soll. Durch Angabe von Doppelpunkt- oder gleichwertigen Namen / Wert-Paaren kann jede Umgebungsvariable überschrieben werden. In diesem Beispiel überschreibt "server.port:0" die Standardporteinstellung des Servers. Normalerweise verwendet der Server die angegebene Portnummer, der Wert 0 hat jedoch eine besondere Bedeutung. Wenn der Wert 0 ist, wird Spring Boot angewiesen, die Ports in der Hostumgebung zu scannen und den Server an einem beliebigen verfügbaren Port zu starten. Dies ist nützlich, wenn verschiedene Dienste auf den Entwicklungsmaschinen und dem Build-Server unterschiedliche Ports belegen, die möglicherweise mit dem Anwendungsport kollidieren. In diesem Fall wird die Anwendung nicht gestartet. Zweitens: Wenn wir mehrere Integrationstests mit unterschiedlichen Anwendungskontexten erstellen, können diese auch kollidieren, wenn die Tests gleichzeitig ausgeführt werden.
  5. Wir haben Zugriff auf den Anwendungskontext und können mithilfe von Autowiring Springbeans injizieren.
  6. Der @Value("${local.server.port}”) wird in die tatsächlich verwendete Portnummer aufgelöst.
  7. Wir erstellen einige Entitäten, die wir zur Validierung verwenden können.
  8. Die MongoDB-Datenbank wird für jeden Test gelöscht und neu initialisiert, sodass immer ein bekannter Zustand geprüft wird. Da die Reihenfolge der Tests nicht definiert ist, besteht die Möglichkeit, dass der Test testFetchAll () fehlschlägt, wenn er nach dem Test testDeletetripleHHH () ausgeführt wird.
  9. Wir weisen Rest Assured an, den richtigen Port zu verwenden. Es handelt sich um ein Open Source-Projekt, das eine Java-DSL zum Testen unruhiger Dienste bereitstellt
  10. Tests werden mithilfe von Rest Assured implementiert. Wir können die Tests mithilfe des TestRestTemplate oder eines anderen http-Clients implementieren. Ich verwende jedoch Rest Assured, da wir mit RestDocs eine präzise Dokumentation schreiben können

Laden verschiedener yaml-Dateien [oder Eigenschaften] oder Überschreiben einiger Eigenschaften

Wenn wir @SpringApplicationConfiguration , wird die Konfiguration von application.yml [Eigenschaften] verwendet, was in bestimmten Situationen nicht angemessen ist. @TestPropertySource die Eigenschaften zu überschreiben, können wir die Annotation @TestPropertySource .

@TestPropertySource(
        properties = {
                "spring.jpa.hibernate.ddl-auto=create-drop",
                "liquibase.enabled=false"
        }
)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{

    // ...

}

Wir können das properties- Attribut von @TestPropertySource , um die @TestPropertySource spezifischen Eigenschaften zu überschreiben. In obigem Beispiel überschreiben wir die Eigenschaft spring.jpa.hibernate.ddl-auto , create-drop zu create-drop . Und liquibase.enabled auf false .

Laden einer anderen Yml-Datei

Wenn Sie verschiedene Yml- Dateien vollständig zum Testen laden möchten, können Sie das Attribut location auf @TestPropertySource .

@TestPropertySource(locations="classpath:test.yml")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{

    // ...

}

Alternativ Optionen

Option 1:

Sie können auch eine andere Yml- Datei laden, indem Sie eine Yml- Datei in das Verzeichnis test > resource

Option 2:

Verwenden der Annotation @ActiveProfiles

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@ActiveProfiles("somename")
public class MyIntTest{
}

Sie können sehen, dass wir @ActiveProfiles Annotation verwenden, und wir übergeben den Namen als Wert.

Erstellen Sie eine Datei namens application-somename.yml und der Test lädt diese Datei.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow