Mock-binlar va spy-binlar
Testlarni bajarishda ba'zan ilova kontekstidagi ma'lum komponentlarni imitatsiya qilish zarur bo'ladi. Misol uchun, sizda rivojlantirish davomida mavjud bo'lmagan biror masofaviy xizmat uchun fasad bo'lishi mumkin. Imitatsiya qilish shuningdek real muhitda qiyin bo'lgan xatolarni simulyatsiya qilish kerak bo'lganda foydali bo'lishi mumkin.
Spring Boot @MockBean annotatsiyasini o'z ichiga oladi, bu ilova kontekstida bino uchun Mockito-imitatsiyani aniqlash uchun ishlatilishi mumkin. Yangi binolar qo'shish yoki mavjud bin definitsiyasini almashtirish uchun annotatsiyani qo'llash mumkin. Annotatsiyani bevosita test sinflari uchun, test ichidagi maydonlar uchun yoki @Configuration annotatsiyali sinflar va maydonlar uchun ishlatish mumkin. Maydon bilan ishlatganda, yaratilgan imitatsiya qilingan obyekt instance ham qo'shiladi. Mock-binlar har bir test metodidan keyin avtomatik ravishda resetlanadi.
Agar test Spring Boot test annotatsiyalaridan birini (masalan, @SpringBootTest) ishlatsa, bu funksiya avtomatik ravishda faollashadi. Bu funksiyani boshqa turdagi tashkilot bilan ishlatish uchun, quyidagi misolda ko'rsatilganidek, eshituvchilarni qo'shing:
@ContextConfiguration(classes = MyConfig.class) @TestExecutionListeners({ MockitoTestExecutionListener.class, ResetMocksTestExecutionListener.class }) class MyTests { // ... }
@ContextConfiguration(classes = [MyConfig::class]) @TestExecutionListeners( MockitoTestExecutionListener::class, ResetMocksTestExecutionListener::class ) class MyTests { // ... }
Keyingi misolda mavjud RemoteService binini imitatsiya qilingan realizatsiya bilan almashtirish ko'rsatilgan:
@SpringBootTest class MyTests { @Autowired private Reverser reverser; @MockBean private RemoteService remoteService; @Test void exampleTest() { given(this.remoteService.getValue()).willReturn("spring"); String reverse = this.reverser.getReverseValue(); // qo'shilgan RemoteService chaqiriq qiladi assertThat(reverse).isEqualTo("gnirps"); } }
@SpringBootTest class MyTests(@Autowired val reverser: Reverser, @MockBean val remoteService: RemoteService) { @Test fun exampleTest() { given(remoteService.value).willReturn("spring") val reverse = reverser.reverseValue // qo'shilgan RemoteService chaqiriq qiladi assertThat(reverse).isEqualTo("gnirps") } }
@MockBean annotatsiyasini ilova konteksti yangilanishi paytida ishlatiladigan bin logikasini imitatsiya qilish uchun ishlatish mumkin emas. Testni amalga oshirish paytida ilova konteksti yangilanishi allaqachon tugallangan, va imitatsiya logikasini sozlash uchun juda kech bo'ladi. Bu holatda biz
@Bean annotatsiyasi bilan belgilanadigan metodidan foydalanishni taklif etamiz, imitatsiya obyektini yaratish va sozlash uchun.
Shuningdek, @SpyBean annotatsiyasini ishlatib, mavjud bina bo'yicha Mockito spy obyektini qo'shish mumkin.
final deb e'lon qiladilar. Bu Mockito freyvmorkini to'g'ri ishlashini to'xtatadi, chunki u
final metodlarni imitatsiya yoki kuzata olmaydi. Agar
final metodlarni kuzatish yoki imitatsiya qilish kerak bo'lsa, Mockito-ni ichki obyektlar konstruktoridan foydalanishga sozlang, ilovangizning testli bog'lanishlariga
org.mockito:mockito-inline qo'shib. Bu Mockito-ga
final metodlarni kuzatishga va imitatsiya qilishga imkon beradi.
@MockBean yoki
@SpyBean annotatsiyalarini ishlatish kesh kalitiga ta'sir qiladi, ehtimol kontekstlar sonini oshiradi.
@SpyBean annotatsiyasini qo'llanilayotgan metodlar bilan kuzatish uchun ishlatsangiz,
@Cacheable bilan belgilangan metodlarni nomi bilan bog'langani va ilovangiz
-parameters parametri bilan kompilatsiyalangan bo'lishi kerak ekanligiga ishonch hosil qiling. Bu kesh infrastrukturasi binga yetilganida parametr nomlariga kirish imkoniyatini kafolatlaydi.
@SpyBean anotatsiyasi Spring-da proksiyaga qo'shilgan binni kuzatish uchun ishlatilsa, ba'zi situatsiyalarda Spring proksi-ni olib tashlash kerak bo'lishi mumkin, masalan,
given yoki
when yordamida kutilyotgan voqealarni o'rnatish paytida. Buning uchun
AopTestUtils.getTargetObject(yourProxiedSpy) ishlatiladi.
Avtokonfiguratsiyalangan testlar
Spring Boot-da avtokonfiguratsiya tizimi ilovalar bilan ajoyib ishlaydi, lekin ba'zida testlar uchun ortiqcha bo'lishi mumkin. Ko'pincha "qatlam" ilovasini testlash uchun faqat kerakli qismlarini yuklash amaliy hisoblanadi. Misol uchun, Spring MVC kontrollarlarini URL-larni to'g'ri ko'rsatishini ta'minlash kerak bo'lishi mumkin, lekin bu testlarga ma'lumotlar bazasini qo'shmaslik yoki JPA-entitylarni testlash kerak bo'lishi mumkin, lekin veb-darajasi bu testlarni bajarishda qiziqishdir.
spring-boot-test-autoconfigure moduli bunday "qatlamlar" avto konfiguratsiyasi uchun bir qator anotatsiyalarni o'z ichiga oladi. Har biri bir xil ishlaydi, @...Test shaklida anotatsiya bo'lib, ApplicationContextni yuklaydi va @AutoConfigure... shaklida konfigratsiyalash parametrlarini sozlash uchun bir yoki bir nechta anotatsiyalarni o'z ichiga oladi.
@...Test anotatsiyalari uchun
excludeAutoConfiguration atributini taqdim etadi. Alternativ variant sifatida
@ImportAutoConfiguration#exclude anotatsiyasini ishlatishingiz mumkin.
@...Test anotatsiyasini tanlab va boshqa "qatlamlar"ni qo'lda kimlar uchun
@AutoConfigure... anotatsiya qo'shing.
@AutoConfigure... anotatsiyalarini standart
@SpringBootTest anotatsiyasi bilan ishlatishingiz mumkin. Agar ilovangiz qatlamlarini yaratishga qiziqmasangiz, lekin avtokonfiguratsiyalangan testli binlardan ba'zi birlarini talab qilinsa, ushbu kombinatsiyani ishlatishingiz mumkin.
Avtokonfiguratsiyalangan JSON testlar
JSON obyektlarining seriyalizatsiya va deserializatsiyasi kutilgan tarzda ishlashiga ishonch hosil qilish uchun @JsonTest anotatsiyasidan foydalanishingiz mumkin. @JsonTest anotatsiyasi mavjud qo'llab-quvvatlangan JSON mapperini avtomatik ravishda sozlaydi, ular quyidagi kutubxonalardan biri bo'lishi mumkin:
-
Jacksondagi
ObjectMapper,@JsonComponentbilan anotatsiyalangan har qanday binlarni va Jacksondagi har qandayModulesni aniqlaydi -
Gson -
Jsonb
@JsonTest anotatsiyasi tomonidan faollashtirilgan avtokonfiguratsiyalar ro'yxatini hujjatning ilovasida topishingiz mumkin.
Agar avtokonfiguratsiya elementlarini sozlashingiz kerak bo'lsa, @AutoConfigureJsonTesters anotatsiyasidan foydalanishingiz mumkin.
Spring Boot JSONAssert va JsonPath kutubxonalarini tekshirish uchun mo'ljallangan AssertJ asosidagi yordamchi sinflarni o'z ichiga oladi. JacksonTester, GsonTester, JsonbTester va BasicJsonTester sinflarini Jackson, Gson, Jsonb va Strings kutubxonalari uchun moslashtirish mumkin. Test sinfi har qanday yordamchi maydoni @JsonTest annotatsiyasi bilan ishlatishda @Autowired bilan belgilanishi mumkin. Keyingi misolda Jackson kutubxonasi uchun test sinfi ko'rsatilgan:
@JsonTest class MyJsonTests { @Autowired private JacksonTester<VehicleDetails> json; @Test void serialize() throws Exception { VehicleDetails details = new VehicleDetails("Honda", "Civic"); // Test bilan bir bo'limdagi ".json" fayli uchun da'vo assertThat(this.json.write(details)).isEqualToJson("expected.json"); // Yoki JSON yo'li asosidagi da'volardan foydalanamiz assertThat(this.json.write(details)).hasJsonPathStringValue("@.make"); assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda"); } @Test void deserialize() throws Exception { String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}"; assertThat(this.json.parse(content)).isEqualTo(new VehicleDetails("Ford", "Focus")); assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford"); } }
@JsonTest class MyJsonTests(@Autowired val json: JacksonTester<VehicleDetails>) { @Test fun serialize() { val details = VehicleDetails("Honda", "Civic") // Test bilan bir bo'limdagi ".json" fayli uchun da'vo assertThat(json.write(details)).isEqualToJson("expected.json") // Yoki JSON yo'li asosidagi da'volardan foydalanamiz assertThat(json.write(details)).hasJsonPathStringValue("@.make") assertThat(json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda") } @Test fun deserialize() { val content = "{\"make\":\"Ford\",\"model\":\"Focus\"}" assertThat(json.parse(content)).isEqualTo(VehicleDetails("Ford", "Focus")) assertThat(json.parseObject(content).make).isEqualTo("Ford") } }
@JsonTest annotatsiyasi qo'llanilmasa,
@Before annotatsiyalangan metodda yordamchi sinfning
initFields metodini chaqirish orqali.
Agar Spring Boot AssertJ asosidagi yordamchi sinflari JSON yo'lidagi raqam qiymatiga da'vo qo'shish uchun ishlatilsa, turiga ko'ra isEqualTo ishlatmang. Buning o'rniga, AssertJ'da satisfies funktsiyasini ishlatib, kutilayotgan shartga mos kelishini da'volang. Masalan, quyidagi misolda kutilayotgan raqamning 0.15 yaqinida ekanligi va shift 0.01 ichida ekanligini da'volangan:
@Test
void someTest() throws Exception {
SomeObject value = new SomeObject(0.152f);
assertThat(this.json.write(value)).extractingJsonPathNumberValue("@.test.numberValue")
.satisfies((number) -> assertThat(number.floatValue()).isCloseTo(0.15f, within(0.01f)));
}
@Test
fun someTest() {
val value = SomeObject(0.152f)
assertThat(json.write(value)).extractingJsonPathNumberValue("@.test.numberValue")
.satisfies(ThrowingConsumer { number ->
assertThat(number.toFloat()).isCloseTo(0.15f, within(0.01f))
})
}
Avtokonfiguratsiyalangan Spring MVC testlari
Spring MVC kontrollarlarini kutilgan funksionallik uchun tekshirish uchun @WebMvcTest annotatsiyasidan foydalaning. @WebMvcTest annotatsiyasi Spring MVC infrastrukturasi va @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, Filter, HandlerInterceptor, WebMvcConfigurer, WebMvcRegistrations va HandlerMethodArgumentResolverni cheklovchi binlarni avtomatik tarzda sozlaydi. @Component va @ConfigurationProperties annotatsiyalari bilan belgilangan binlar @WebMvcTest annotatsiyasi bilan skanerlashga kiritilmaydi. @ConfigurationProperties annotatsiyali binlarni qo'shish uchun @EnableConfigurationProperties annotatsiyasidan foydalanishingiz mumkin.
Module, testda
@Import annotatsiyasini ishlatib, qo'shimcha konfiguratsiyali sinflarni import qilishingiz mumkin.
Ko'pincha @WebMvcTest bir nazoratga cheklangan bo'lib, kerakli aloqali obyektlar uchun imitatsiya realizatsiyalarini berish uchun @MockBean annotatsiyasi bilan birgalikda ishlatiladi.
@WebMvcTest avtomatik tarzda MockMvcni so'zlashini ham bajaradi. Mock MVC nazoratlar MVC-ni tez va samarali test qilish uchun to'liq bir HTTP serveri ishlatmasdan taqdim etiladigan usul.
@WebMvcTest annotatsiyasiz
MockMvcni avtomatik tarzda sozlashingiz mumkin (masalan,
@SpringBootTest annotatsiyasi bilan), uni
@AutoConfigureMockMvc yordamida anotatsiya qilib. Keyingi misolda
MockMvc ishlatilgan:
@WebMvcTest(UserVehicleController.class) class MyControllerTests { @Autowired private MockMvc mvc; @MockBean private UserVehicleService userVehicleService; @Test void testExample() throws Exception { given(this.userVehicleService.getVehicleDetails("sboot")) .willReturn(new VehicleDetails("Honda", "Civic")); this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN)) .andExpect(status().isOk()) .andExpect(content().string("Honda Civic")); } }
@WebMvcTest(UserVehicleController::class) class MyControllerTests(@Autowired val mvc: MockMvc) { @MockBean lateinit var userVehicleService: UserVehicleService @Test fun testExample() { given(userVehicleService.getVehicleDetails("sboot")) .willReturn(VehicleDetails("Honda", "Civic")) mvc.perform(MockMvcRequestBuilders.get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN)) .andExpect(MockMvcResultMatchers.status().isOk) .andExpect(MockMvcResultMatchers.content().string("Honda Civic")) } }
@AutoConfigureMockMvc annotatsiyasidagi atributlardan foydalanishingiz mumkin.
HtmlUnit va Selenium ishlatganingizda, avtokonfiguratsiya HtmlUnit uchun WebClient binini va/va' WebDriver binini Selenium uchun taqdim etadi. Keyingi misolda HtmlUnit ishlatilgan:
@WebMvcTest(UserVehicleController.class) class MyHtmlUnitTests { @Autowired private WebClient webClient; @MockBean private UserVehicleService userVehicleService; @Test void testExample() throws Exception { given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new VehicleDetails("Honda", "Civic")); HtmlPage page = this.webClient.getPage("/sboot/vehicle.html"); assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic"); } }
@WebMvcTest(UserVehicleController::class) class MyHtmlUnitTests(@Autowired val webClient: WebClient) { @MockBean lateinit var userVehicleService: UserVehicleService @Test fun testExample() { given(userVehicleService.getVehicleDetails("sboot")).willReturn(VehicleDetails("Honda", "Civic")) val page = webClient.getPage<HtmlPage>("/sboot/vehicle.html") assertThat(page.body.textContent).isEqualTo("Honda Civic") } }
WebDriver binlarini maxsus "hizmat ko'rsatish sohasiga" joylashtiradi, har bir testdan keyin drayverni tugatish va yangi misolini qo'shish uchun. Agar bunday ishlash usuli ortiqcha bo'lsa, sizning
WebDriver aniqlashda
@Bean annotatsiyasi bilan
@Scope("singleton") qo'shishingiz mumkin.
webDriver xizmat ko'rsatish sohasining Spring Boot tomonidan yaratilgani foydalanuvchi tomonidan aniqlangan bir xil nom bilan xizmat ko'rsatish sohasini almashtiradi. Agar sizning o'zingizning
webDriver xizmat ko'rsatish sohangiz mavjud bo'lsa, unda
@WebMvcTest annotatsiyasini ishlatishda to'xtalishi mumkin.
Agar classpath-da Spring Security mavjud bo'lsa, @WebMvcTest annotatsiyasi WebSecurityConfigurer binlarini ham skanerlaydi. Bunday testlar uchun xavfsizlik vositalarini to'liq o'chirib qo'yish o'rniga, Spring Security testlarini qo'llab-quvvatlash vositalaridan foydalanishingiz mumkin.
Avtokonfiguratsiyalangan Spring WebFlux testlari
Spring WebFlux kontrollarining kutilgan tarzda ishlashiga ishonch hosil qilish uchun @WebFluxTest annotatsiyasidan foydalanishingiz mumkin. @WebFluxTest annotatsiyasi Spring WebFlux infrastrukturasi va @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, WebFilter va WebFluxConfigurerni cheklovchi binlarni avtomatik tarzda sozlaydi. @Component va @ConfigurationProperties annotatsiyalari bilan belgilangan binlar @WebFluxTest annotatsiyasi bilan skanerlashga kiritilmaydi. @ConfigurationProperties annotatsiyali binlarni qo'shish uchun @EnableConfigurationProperties annotatsiyasidan foydalanishingiz mumkin.
Moduleni, testda
@Import annotatsiyasini ishlatib, qo'shimcha konfiguratsiyali sinflarni import qilishingiz mumkin.
Ko'pincha @WebFluxTest bir nazoratga cheklangan bo'lib, kerakli aloqali obyektlar uchun imitatsiya realizatsiyalarini berish uchun @MockBean annotatsiyasi bilan birgalikda ishlatiladi.
@WebFluxTest annotatsiyasi shuningdek WebTestClientni avtomatik tarzda sozlaydi, bu esa to'liq HTTP serveri ishlatmasdan WebFlux kontrollarini tez va samarali test qilish imkonini beradi.
@WebFluxTest annotatsiyasiz
WebTestClientni avtomatik tarzda sozlashingiz mumkin (masalan,
@SpringBootTest annotatsiyasi bilan), uni
@AutoConfigureWebTestClient yordamida anotatsiyalash orqali. Keyingi misolda
@WebFluxTest annotatsiyasi va
WebTestClient ishlatilgan sinf ko'rsatilgan:
@WebFluxTest(UserVehicleController.class) class MyControllerTests { @Autowired private WebTestClient webClient; @MockBean private UserVehicleService userVehicleService; @Test void testExample() { given(this.userVehicleService.getVehicleDetails("sboot")) .willReturn(new VehicleDetails("Honda", "Civic")); this.webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo("Honda Civic"); } }
@WebFluxTest(UserVehicleController::class) class MyControllerTests(@Autowired val webClient: WebTestClient) { @MockBean lateinit var userVehicleService: UserVehicleService @Test fun testExample() { given(userVehicleService.getVehicleDetails("sboot")) .willReturn(VehicleDetails("Honda", "Civic")) webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange() .expectStatus().isOk .expectBody<String>().isEqualTo("Honda Civic") } }
WebTestClientni simulyatsiya qilingan veb-ilovada ishlatish WebFluxda faqat ishlaydi.
@WebFluxTest anotatsiyasi funktsional veb-freyvmork yordamida ro'yxatdan o'tgan marshrutlarni aniqlash imkoniyatiga ega emas.
RouterFunction binlarini kontekstdagi testlar uchun qo'shishni o'ylab ko'ring,
@Import anotatsiyasi bilan
RouterFunctionni o'z qiling yoki
@SpringBootTest anotatsiyasi bilan.
@WebFluxTest anotatsiyasi
SecurityWebFilterChain tipi bo'lgan
@Bean sifatida ro'yxatdan o'tkazilgan maxsus xavfsizlik konfiguratsiyasini aniqlash imkoniyatiga ega emas. Bu konfiguratsiyani testda ishlatish uchun, bin ro'yxatdan o'tkazuvchi konfiguratsiyani
@Import anotatsiyasi bilan import qiling yoki
@SpringBootTest anotatsiyasi bilan.
GO TO FULL VERSION