Spring Webflux и Spring Web — это два совершенно разных веб-стека. Однако Spring Webflux продолжает поддерживать модель программирования на основе аннотаций.
Конечная точка, определенная с использованием этих двух стеков, может выглядеть одинаково, но способ проверки такой конечной точки довольно различен, и пользователь, пишущий такую конечную точку, должен знать, какой стек является активным, и соответствующим образом сформулировать тест.
Пример конечной точки
Рассмотрим пример конечной точки на основе аннотации:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.web.bind.annotation.PostMapping</span> import org.springframework.web.bind.annotation.PostMapping</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.web.bind.annotation.RequestBody</span> import org.springframework.web.bind.annotation.RequestBody</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.web.bind.annotation.RequestMapping</span> import org.springframework.web.bind.annotation.RequestMapping</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.web.bind.annotation.RestController</span> import org.springframework.web.bind.annotation.RestController</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">data class Greeting(val message: String)</span> класс данных Greeting (val message: String)</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@RestController</span> @RestController</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@RequestMapping("/web")</span> @RequestMapping ( "/ веб")</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">class GreetingController {</span> class GreetingController {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@PostMapping("/greet")</span> @PostMapping ( "/") Greet</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">fun handleGreeting(@RequestBody greeting: Greeting): Greeting {</span> fun handleGreeting (@RequestBodyreeting: Greeting): Приветствие {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">return Greeting("Thanks: ${greeting.message}")</span> return Greeting ("Спасибо: $ {reeting.message}")</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span> |
Тестирование с помощью Spring Web
Если для создания этого приложения использовался стартер Spring Boot 2 с Spring Web в качестве стартера, это указывается с помощью файла сборки Gradle следующим образом:
|
1
|
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">compile('org.springframework.boot:spring-boot-starter-web')</span> компиляции ( 'org.springframework.boot: весна-загрузка-стартер-сеть')</span> |
тогда проверка такой конечной точки будет использовать Mock Web Runtime, называемую Mock MVC :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.junit.Test</span> импорт org.junit.Test</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.junit.runner.RunWith</span> import org.junit.runner.RunWith</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.beans.factory.annotation.Autowired</span> import org.springframework.beans.factory.annotation.Autowired</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest</span> import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.test.context.junit4.SpringRunner</span> import org.springframework.test.context.junit4.SpringRunner</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.test.web.servlet.MockMvc</span> import org.springframework.test.web.servlet.MockMvc</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post</span> import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content</span> import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@RunWith(SpringRunner::class)</span> @RunWith (SpringRunner :: класс)</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@WebMvcTest(GreetingController::class)</span> @WebMvcTest (GreetingController :: класс)</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">class GreetingControllerMockMvcTest {</span> class GreetingControllerMockMvcTest {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Autowired</span> @Autowired</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">lateinit var mockMvc: MockMvc</span> lateinit var mockMvc: MockMvc</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Test</span> @Тест</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">fun testHandleGreetings() {</span> fun testHandleGreetings () {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">mockMvc</span> mockMvc</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.perform(</span> .Произвести (</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">post("/web/greet")</span> пост ( "/ веб / Greet")</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.content("""</span> .content ( ""»</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|{</span> | {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|"message": "Hello Web"</span> | "message": "Hello Web"</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|}</span> |}</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">""".trimMargin())</span> ""».TrimMargin ())</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">).andExpect(content().json("""</span> ) .AndExpect (содержание (). JSON ( ""»</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|{</span> | {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|"message": "Thanks: Hello Web"</span> | "message": "Спасибо: Hello Web"</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|}</span> |}</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">""".trimMargin()))</span> ""».TrimMargin ()))</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span> |
Тестирование с помощью Spring Web-Flux
Если, с другой стороны, стартеры Spring-Webflux были задействованы, скажем, со следующей зависимостью Gradle:
|
1
|
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">compile('org.springframework.boot:spring-boot-starter-webflux')</span> компиляции ( 'org.springframework.boot: весна-загрузки-стартер-webflux')</span> |
тогда тест этой конечной точки будет использовать отличный класс WebTestClient , а именно:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
<span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.junit.Test</span> импорт org.junit.Test</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.junit.runner.RunWith</span> import org.junit.runner.RunWith</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.beans.factory.annotation.Autowired</span> import org.springframework.beans.factory.annotation.Autowired</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest</span> import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.http.HttpHeaders</span> import org.springframework.http.HttpHeaders</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.test.context.junit4.SpringRunner</span> import org.springframework.test.context.junit4.SpringRunner</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.test.web.reactive.server.WebTestClient</span> import org.springframework.test.web.reactive.server.WebTestClient</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">import org.springframework.web.reactive.function.BodyInserters</span> import org.springframework.web.reactive.function.BodyInserters</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@RunWith(SpringRunner::class)</span> @RunWith (SpringRunner :: класс)</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@WebFluxTest(GreetingController::class)</span> @WebFluxTest (GreetingController :: класс)</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">class GreetingControllerTest {</span> class GreetingControllerTest {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Autowired</span> @Autowired</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">lateinit var webTestClient: WebTestClient</span> lateinit var webTestClient: WebTestClient</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">@Test</span> @Тест</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">fun testHandleGreetings() {</span> fun testHandleGreetings () {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">webTestClient.post()</span> webTestClient.post ()</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.uri("/web/greet")</span> .uri ( "/ веб / Greet")</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.header(HttpHeaders.CONTENT_TYPE, "application/json")</span> .header (HttpHeaders.CONTENT_TYPE, "application / json")</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.body(BodyInserters</span> .Body (BodyInserters</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.fromObject("""</span> .fromObject ( ""»</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|{</span> | {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|</span> |</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">"message": "Hello Web"</span> "message": "Hello Web"</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|}</span> |}</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">""".trimMargin()))</span> ""».TrimMargin ()))</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.exchange()</span> .exchange ()</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.expectStatus().isOk</span> .expectStatus (). isOk</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.expectBody()</span> .expectBody ()</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">.json("""</span> .json ( ""»</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|{</span> | {</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|</span> |</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">"message": "Thanks: Hello Web"</span> "message": "Спасибо: Hello Web"</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">|}</span> |}</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">""".trimMargin())</span> ""».TrimMargin ())</span> <span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span><span class="notranslate" onmouseover="_tipon(this)" onmouseout="_tipoff()"><span class="google-src-text" style="direction: ltr; text-align: left">}</span> }</span> |
Вывод
Легко предположить, что, поскольку модель программирования выглядит очень похожей при использовании стеков Spring Web и Spring Webflux, тесты для такого унаследованного теста с использованием Spring Web продолжались бы до Spring Webflux, однако это не так, поскольку у нас есть разработчик помнить о базовом стеке, который вступает в игру, и формулировать тест соответствующим образом. Я надеюсь, что этот пост проясняет, как такой тест должен быть обработан.
| Смотрите оригинальную статью здесь: Аннотированные контроллеры — Spring Web / Webflux и Тестирование
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |