JavaRush /Kurslar /All lectures for TK purposes /Spring Boot-da Programma Test Edilişi

Spring Boot-da Programma Test Edilişi

All lectures for TK purposes
Dereje , Sapak
Elýeterli

Spring Boot gurnalan programma test edilişini ýeňilleşdirýän birnäçe utilit we annotasiýalary üpjün edýär. Test goldawy iki modul bilen üpjün edilýär: spring-boot-test esasy elementleri öz içine alýar, şol bir wagtyň özünde spring-boot-test-autoconfigure testler üçin awtomaçn konfigurasiýany goldaýar.

Köp sanly programmist "başlaýjy" spring-boot-starter-test ulanýarlar, ol iki test modullaryny, şeýle hem JUnit Jupiter, AssertJ, Hamcrest we başga-da birnäçe peýdaly kitaphanany import edýär.

Eger siziň JUnit 4 ulanýan testleriňiz bolsa, olary işlemek üçin JUnit 5-njiň köne hereketlendirijisini ulanyp bilersiňiz. Köne hereketlendirijini ulanmak üçin aşakdaky mysalda görkezilişi ýaly junit-vintage-engine-den garaşlylygy goşup bilersiňiz:

<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

hamcrest-core org.hamcrest:hamcrest-iň peýdasyna çykaryldy, ol spring-boot-starter-test-iň bir bölegidir.

Test Meýdanynyň Garaşlylyklary

"başlaýjy" spring-boot-starter-test (test scope-da) aşakdaky kitaphanalary üpjün edýär:

  • JUnit 5: Java programmalaryň bir görnüşli test edilmegi üçin de-fakto standart.

  • Spring Test we Spring Boot Test: Spring Boot programmalary üçin utilit we integrasiýa test goldawy.

  • AssertJ: Akynly tassyklamalar kitaphanasy.

  • Hamcrest: Meçerli zatlar (matchers) (şeýle hem çäklendirmeler ýa-da predikatlar hökmünde bellidir).

  • Mockito: Java meýdançasy üçin imitasiýalar (mocking)

  • JSONassert: JSON üçin tassyklamalar kitaphanasy.

  • JsonPath: JSON üçin XPath.

Adatça, bu umumy kitaphanalar test ýazmakda peýdaly bolýar. Eger bu kitaphanalar siziň islegleriňizi kanagatlandyrsa, siz öz islegine görä goşmaça test garaşlylyklaryny goşup bilersiňiz.

Spring Programmalaryň Test Edilişi

Garaşlylyklaryň girizilmeginiň esasy artykmaçlyklaryndan biri, kodyň bir görnüşli test edilişini ýeňilleşdirmekdir. Siz Spring ulanmadan new operator bilen obýektleriň nusgalaryny döredip bilersiňiz. Şeýle hem hakyky garaşlylyklaryň ýerine imitasiýa obýektlerini ulanyp bilersiňiz.

Köp sanly ýagdaýda bir görnüşli test çäklerinden çykmak we integrasiýa test başlamak talap edilýär (Spring-den ApplicationContext bilen). Programma ýa-da başga infrastruktura bilen baglanyşygyny hökmany etmän, integrasiýa testleri geçirip bilmek peýdalydyr.

Spring Framework şeýle integrasiýa testleri üçin aýratyn test moduly öz içine alýar. Siz garaşlylygy göni org.springframework:spring-test-den ýazyp bilersiňiz ýa-da geçiriş bilen birikme üçin "başlaýjy" spring-boot-starter-test ulanyp bilersiňiz.

Spring Boot Programmalaryň Test Edilişi

Spring Boot programma – bu Spring üçin ApplicationContext-dir, şonuň üçin ony test etmek üçin Spring-iň wanil kontekstinde ýerine ýetirilýän operasiýalardan başga zat talap etmeýär.

Daşary häsiýetler, logirleme we beýleki Spring Boot aýratynlyklary kontekstde meýilleşdirilýär, diňe siz SpringApplication ony döretmek üçin ulansaňyz.

Spring Boot @SpringBootTest annotasiýasyny üpjün edýär, ony Spring Boot-iň aýratynlyklary talap edilen wagtda spring-test üçin adaty annotasiýa @ContextConfiguration alternatiwasy hökmünde ulanyp bilersiňiz. Annotasiýa testlerde ulanylýan ApplicationContext-i SpringApplication arkaly döredýär. @SpringBootTest annotasiýasyna goşmaça, siziň programmaňyzyň has anyk dilimlerini test etmek üçin başga-da birnäçe annotasiýa üpjün edilýär.

Eger siz JUnit 4 ulansañyz, şeýle hem annotasiýalary göz ardyna almaň, @RunWith(SpringRunner.class) testine goşmagy ýatdan çykarmaň. Eger siz JUnit 5 ulansañyz, onuň ekwiwalenti annotasiýasyny @ExtendWith(SpringExtension.class) goşmak hökman däl, sebäbi @SpringBootTest we beýleki @...Test annotasiýalary bilen eýýäm bellendi.

Adaty ýagdaýda @SpringBootTest annotasiýasy serweri işledip goýmaýar. Siz öz testleriňiziň durmuşa geçirilişini has anyklaşdyrmak üçin @SpringBootTest annotasiýasynyň webEnvironment atributyny ulanyp bilersiňiz:

  • MOCK(adaty): ApplicationContext web kontekstini ýükläp, web gurşawynyň imitasiýa obýektini üpjün edýär. Bu anotasiýany ulanyp, gurulan serwerler işledilmeýär. Eger web gurşawy sizin classpath-de elýeterli däl bolsa, bu tertip adaty web däl ApplicationContext döretmäge çalt geçýär. Onuň işini @AutoConfigureMockMvc ýa-da @AutoConfigureWebTestClient annotasiýasy bilen bilelikde test etmek üçin ulanyp bilersiňiz.

  • RANDOM_PORT: WebServerApplicationContext gurşawy web gurşawynyň hakyky görnüşini üpjün edýär. Gurulan serwerler işledilýär we tötänleýin porty diňleýär.

  • DEFINED_PORT: WebServerApplicationContext gurşawy web gurşawyň has hakyky görnüşini üpjün edýär. Gurulan serwerler işledilip, belgilenen porty berýär (application.properties faýlyndan) ýa-da adaty port 8080.

  • NONE: ApplicationContext-i SpringApplication arkaly belleýär, emma hiç hili web gurşawyny (imitasiýa ýa-da başga) üpjün etmeýär.

Eger siziň teste annotasiýa @Transactional goşulsa, ol adaty ýagdaýda her test metodynyň soňunda transaksiýany yzyna öwürýär. Emma RANDOM_PORT ýa-da DEFINED_PORT ýaly hakykat gurşawynda serwerleri we HTTP-müşderi bölümlerini goýmak şol bir wagtda transaksiýalarda yzyna öwürülmeýär.
Annotasiýa @SpringBootTest webEnvironment = WebEnvironment.RANDOM_PORT hem dürli tötänleýin port üstünden dolandyrmak serwer işini açýar, eger-de programma başga portda dolandyrmak serwerini ulanýan bolsa.

Web Programmasynyň Tübin Kesgitlemek

Eger Spring MVC elýeterli bolsa, adaty MVC esasynda programmanyň konteksti sazlanar. Diňe Spring WebFlux bar bolsa, ol tapylyp, programmanyň konteksti WebFlux-ä esaslanýar.

Eger frameworklaryň ikisi hem bar bolsa, Spring MVC öňe sürülýär. Bu ýagdaýda reaktiw web programmany test etmek üçin spring.main.web-application-type häsiýetini kesgitlär:

Java
import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest(properties = "spring.main.web-application-type=reactive") class MyWebFluxTests { // ... } 
Kotlin
import org.springframework.boot.test.context.SpringBootTest @SpringBootTest(properties = ["spring.main.web-application-type=reactive"]) class MyWebFluxTests { // ... } 

Test Konfigurasiýasyny Kesgitlär

Eger siz Spring Test Framework bilen tanyş bolsaňyz, onda @ContextConfiguration(classes=…​) ulanmaňa öwrenişen bolsaňyz gerek, haçanda Spring üçin haýsy @Configuration ýükläp bolar. Mysal üçin, siz köplenç testiňizde @Configuration bilen bellikli içki klassa basgaça ulanýardyňyz.

Spring Boot programmalar test edilende, bu adaty talap edilmeýär. Spring Boot-yň @*Test annotasiýalary haýsy ilkinji konfigurasiýaňyzy bellik etmedigiňiz ýagdaýynda awtomatilk tapar.

Gözleg algoritmi testi öz içine alýan bukjanyň içinden başlaýar we @SpringBootApplication ýa-da @SpringBootConfiguration bilen belliklenen klassy tapmazdan galýar. Eger-de siz kodyňyzy laýyk derejede gurluşlandyran bolsaňyz, esasy konfigurasiýany tapmak mümkin bolup biler.

Programmanyň aýratyn gatlaklaryny barlamak üçin test annotasiýasy ulanylýanda, programmanyň esasy metod klassynda belli bir ugra degişli konfigurasiýa parametrlerini goşmagyň öňüni alyň.

Komponentleri skanirlemegiň esasy konfigurasiýasy, @SpringBootApplication annotasiýasy bilen baglanyşykly, kabul edilen dilimleriň işleýşi ýaly bolmagyny üpjün etmek üçin ulanylýan çyzyk filtirlerini kesgitleýär. Eger-de @SpringBootApplication bilen belliklenen klass üçin @ComponentScan bilen açyk buýruk ulanylýan bolsa, bu filtirler işlemeýär. Eger siz dilimleri almaga degişli bolsa, olary täzeden kesgitläň.

Eger ilkinji konfigurasiýany düzmek gerek bolsa, test annotasiýasy bilen bellikli içki klass ulanyp bilersiňiz @TestConfiguration. Içki klas hökmünde ulanylan @Configuration bilen belliklenmedik, ol programmanyň esasy konfigurasiýasyny ulanyp ulanylýar, lakin @TestConfiguration bilen bellikli içki klass programmanyň esasy konfigurasiýasyny doldurýar.

Spring-iň test çarçuwalygy programmanyň kontekstleriniň arasynda keşiň ulanýar. Şeýlelikde, testler bir konfigurasiýany (belli bolmadyk ýagdaýynda) ulanýan bolsa, kontekstiň işlenmegi diňe bir gezek bolup geçýär.

Test Konfigurasiýasyny Çykarmak

Eger siziň programmanyň komponent skaneri ulanýan (meselem, @SpringBootApplication ýa-da @ComponentScan annotasiýalary bilen) bolsa, siz belli bir testler üçin döredilen ýokary derejeli konfigurasiýa klasslary bilen işleşip bilersiňiz, olar hemme ýerde haýal döredilip tapylýar.

Test annotasiýasy @TestConfiguration belleklemek üçin ulanylyp bilner içki test klassda esasy konfigurasiýa sazlamak üçin. Şeýle-de, @TestConfiguration bilen bellikli ýokary derejeli klassy bellemek, src/test/java içindäki klasslaryň skanirleme wagtynda tanaw edilmeýänini görkezýär. Soňra, mysalda görkezilişi ýaly, bu klassy açyk görnüşde import edip ulanyp bolýar:

Java
import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; @SpringBootTest @Import(MyTestsConfiguration.class) class MyTests { @Test void exampleTest() { // ... } } 
Kotlin
import org.junit.jupiter.api.Test import org.springframework.boot.test.context.SpringBootTest import org.springframework.context.annotation.Import @SpringBootTest @Import(MyTestsConfiguration::class) class MyTests { @Test fun exampleTest() { // ... } } 
Eger @ComponentScan annotasiýasy göni ulanylýan bolsa (ýa-da @SpringBootApplication däl), onda TypeExcludeFilter goşmaly.

Programmanyň Argumentlerini Ulanyş

Eger programma argumentleri kabul edýän bolsa, siz @SpringBootTest annotasiýasy bilen olary args atributy arkaly ýerleşdirip bilersiňiz.

Java
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.test.context.SpringBootTest; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(args = "--app.test=one") class MyApplicationArgumentTests { @Test void applicationArgumentsPopulated(@Autowired ApplicationArguments args) { assertThat(args.getOptionNames()).containsOnly("app.test"); assertThat(args.getOptionValues("app.test")).containsOnly("one"); } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.ApplicationArguments import org.springframework.boot.test.context.SpringBootTest @SpringBootTest(args = ["--app.test=one"]) class MyApplicationArgumentTests { @Test fun applicationArgumentsPopulated(@Autowired args: ApplicationArguments) { assertThat(args.optionNames).containsOnly("app.test") assertThat(args.getOptionValues("app.test")).containsOnly("one") } } 

Imitasiýa Gurşawynda Test Edilişi

Adaty ýagdaýda @SpringBootTest annotasiýasy serweri işledip goýmaýar, onuň ýerine web nokatlary test üçin imitasiýa gurşawyny döredýär.

Spring MVC-de imitasiýa gurşawynda MockMvc ýa-da WebTestClient ulanyp web nokatlaryny barlap bilersiňiz, mysal üçin aşakda görkezilişi ýaly:

Java
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @AutoConfigureMockMvc class MyMockMvcTests { @Test void testWithMockMvc(@Autowired MockMvc mvc) throws Exception { mvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("Hello World")); } // Eger Spring WebFlux classpath-de bar bolsa, WebTestClient bilen MVC-testler dolandyrylýar @Test void testWithWebTestClient(@Autowired WebTestClient webClient) { webClient .get().uri("/") .exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo("Hello World"); } } 
Kotlin
import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.web.reactive.server.WebTestClient import org.springframework.test.web.reactive.server.expectBody import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders import org.springframework.test.web.servlet.result.MockMvcResultMatchers @SpringBootTest @AutoConfigureMockMvc class MyMockMvcTests { @Test fun testWithMockMvc(@Autowired mvc: MockMvc) { mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isOk) .andExpect(MockMvcResultMatchers.content().string("Hello World")) } // Eger Spring WebFlux classpath-de bar bolsa, WebTestClient bilen MVC-testler dolandyrylýar @Test fun testWithWebTestClient(@Autowired webClient: WebTestClient) { webClient .get().uri("/") .exchange() .expectStatus().isOk .expectBody<String>().isEqualTo("Hello World") } } 
Eger diňe web derejesine ünsi jemlemek we doly ApplicationContext işletmek islemeýän bolsaňyz, @WebMvcTest annotasiýasyny ulanyp, alternativ hökmünde göz öňünde tutuň.

WebTestClient ulanyp, Spring WebFlux soňky nokatlaryny, aşakdaky mysalda görkezilişi ýaly barlap bilersiňiz:

Java
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.reactive.server.WebTestClient; @SpringBootTest @AutoConfigureWebTestClient class MyMockWebTestClientTests { @Test void exampleTest(@Autowired WebTestClient webClient) { webClient .get().uri("/") .exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo("Hello World"); } } 
Kotlin
import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.web.reactive.server.WebTestClient import org.springframework.test.web.reactive.server.expectBody @SpringBootTest @AutoConfigureWebTestClient class MyMockWebTestClientTests { @Test fun exampleTest(@Autowired webClient: WebTestClient) { webClient .get().uri("/") .exchange() .expectStatus().isOk .expectBody<String>().isEqualTo("Hello World") } } 

Adatça imitasiýa gurşawynda test geçirilmegi doly servlet konteýner ulanylyşyndan has çalt geçýär. Emma, imitasiýa Spring MVC derejasynda bolup geçýär, servlet konteýner işleriniň ýokarky logikasy bilen bagly kod göni MockMvc bilen test edilip bilmez.

Mysal üçin, Spring Boot-da ýalňyş beýany konteýneriň öz serişdelerine degişlidir. Bu, MVC derejesiniň döredýän we beýan edýän aralyklaryny test etmek mümkin, belli ýalňyş sahypalaryny göni görkezmek mümkin däldir. Eger siziň beýik derejeli nuanslary test isleseňiz, aşakdaky bölümde beýan edilişi ýaly, doly işläp duran serwer işledip bilersiňiz.

Işleýän Serwer Ulgamy Bilen Test

Eger doly işläp duran serweri işletmek isleseňiz, tötänleýin portlaryň ulanylmagyny maslahat berýäris. Siz @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) ulanyňyzda test her gezek işledilende elýeterli port tötänleýin saýlanýar.

@LocalServerPort annotasiýasyny ulanyp, test bilen ulanylýan port bellik edip biler. REST-çaýyrmak üçin döredilen testler, @Autowire bilen belliklenen, WebTestClient baglanýan testler, serweri belliklenen linklere ýol berip, aşakdaky mysalda görkezilişi ýaly, öz spesifik API-sini berip biler:

Java
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.test.web.reactive.server.WebTestClient; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class MyRandomPortWebTestClientTests { @Test void exampleTest(@Autowired WebTestClient webClient) { webClient .get().uri("/") .exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo("Hello World"); } } 
Kotlin
import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context@SpringBootTest.WebEnvironment import org.springframework.test.web.reactive.server.WebTestClient import org.springframework.test.web.reactive.server.expectBody @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class MyRandomPortWebTestClientTests { @Test fun exampleTest(@Autowired webClient: WebTestClient) { webClient .get().uri("/") .exchange() .expectStatus().isOk .expectBody<String>().isEqualTo("Hello World") } } 
WebTestClient ulanyp, hakyky serwerler hem imitasiýa gurşawlarynda ulanyp bolýar.

Bu konfigurasiýa spring-webflux -ni classpath-de goşmak talap edýär. Webflux goşup bilmeýän ýa-da islemeýän bolsaňyz, Spring Boot TestRestTemplate ulanma mümkinçiligini hem üpjün edýär:

Java
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class MyRandomPortTestRestTemplateTests { @Test void exampleTest(@Autowired TestRestTemplate restTemplate) { String body = restTemplate.getForObject("/", String.class); assertThat(body).isEqualTo("Hello World"); } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context@SpringBootTest.WebEnvironment import org.springframework.boot.test.web.client.TestRestTemplate @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class MyRandomPortTestRestTemplateTests { @Test fun exampleTest(@Autowired restTemplate: TestRestTemplate) { val body = restTemplate.getForObject("/", String::class.java) assertThat(body).isEqualTo("Hello World") } } 

WebTestClient Ulanma Konfigurasiýasy

WebTestClient sazlamak üçin, WebTestClientBuilderCustomizer binini sazlaň. Şeýle binalar WebTestClient.Builder arkaly WebTestClient döretmek üçin ulanylýar.

JMX Ulanmak

Test kontekst çarçuwasy konteksti keşe ulanýandygy üçin, JMX tehnologýasy öňünden öçürilip, şol bir domen bilen baglanyşykly komponentleriň hasaba alynmagynyň öňüni alar. Eger şeýle teste MBeanServer-e giriş gerek bolsa, ony hapalaň:

Java
import javax.management.MBeanServer; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(properties = "spring.jmx.enabled=true") @DirtiesContext class MyJmxTests { @Autowired private MBeanServer mBeanServer; @Test void exampleTest() { assertThat(this.mBeanServer.getDomains()).contains("java.lang"); // ... } } 
Kotlin
import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.annotation.DirtiesContext import javax.management.MBeanServer @SpringBootTest(properties = ["spring.jmx.enabled=true"]) @DirtiesContext class MyJmxTests(@Autowired val mBeanServer: MBeanServer) { @Test fun exampleTest() { assertThat(mBeanServer.domains).contains("java.lang") // ... } } 

Metri ýolari Ulanma

Classpath-den garaşly bolmazdan, hasaplaýjy registrler, @SpringBootTest ulanylanda, diňe ýüzerinde saklanmak bilen awtomatik sazlanmaýar.

Eger intigrasiýa testi çarçuwasynda beýleki serwerde metri maglumatlaryny çykarmaly bolsa, @AutoConfigureMetrics bilen bellikläň.

Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION