|
16 | 16 |
|
17 | 17 | package org.springframework.web.reactive.result.method; |
18 | 18 |
|
| 19 | +import java.io.UnsupportedEncodingException; |
19 | 20 | import java.lang.reflect.Method; |
| 21 | +import java.time.Duration; |
| 22 | +import java.time.Instant; |
20 | 23 | import java.util.Arrays; |
21 | 24 |
|
22 | 25 | import org.junit.Test; |
| 26 | +import reactor.core.publisher.Flux; |
23 | 27 | import reactor.core.publisher.Mono; |
24 | 28 | import reactor.test.StepVerifier; |
25 | 29 |
|
| 30 | +import org.springframework.core.io.buffer.DataBuffer; |
| 31 | +import org.springframework.core.io.buffer.DefaultDataBufferFactory; |
26 | 32 | import org.springframework.http.HttpStatus; |
| 33 | +import org.springframework.http.server.reactive.ServerHttpResponse; |
| 34 | +import org.springframework.lang.Nullable; |
27 | 35 | import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; |
28 | 36 | import org.springframework.mock.web.test.server.MockServerWebExchange; |
29 | 37 | import org.springframework.web.bind.annotation.ResponseStatus; |
30 | 38 | import org.springframework.web.reactive.BindingContext; |
31 | 39 | import org.springframework.web.reactive.HandlerResult; |
| 40 | +import org.springframework.web.server.ServerWebExchange; |
32 | 41 | import org.springframework.web.server.UnsupportedMediaTypeStatusException; |
33 | 42 |
|
34 | | -import static org.hamcrest.Matchers.*; |
35 | | -import static org.junit.Assert.*; |
| 43 | +import static org.hamcrest.Matchers.is; |
| 44 | +import static org.junit.Assert.assertEquals; |
| 45 | +import static org.junit.Assert.assertNull; |
| 46 | +import static org.junit.Assert.assertThat; |
| 47 | +import static org.junit.Assert.fail; |
36 | 48 | import static org.mockito.Mockito.any; |
37 | | -import static org.mockito.Mockito.*; |
38 | | -import static org.springframework.web.method.ResolvableMethod.*; |
| 49 | +import static org.mockito.Mockito.mock; |
| 50 | +import static org.mockito.Mockito.when; |
| 51 | +import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get; |
| 52 | +import static org.springframework.web.method.ResolvableMethod.on; |
39 | 53 |
|
40 | 54 | /** |
41 | 55 | * Unit tests for {@link InvocableHandlerMethod}. |
|
45 | 59 | */ |
46 | 60 | public class InvocableHandlerMethodTests { |
47 | 61 |
|
48 | | - private final MockServerWebExchange exchange = |
49 | | - MockServerWebExchange.from(MockServerHttpRequest.get("http://localhost:8080/path")); |
| 62 | + private final MockServerWebExchange exchange = MockServerWebExchange.from(get("http://localhost:8080/path")); |
50 | 63 |
|
51 | 64 |
|
| 65 | + @Test |
| 66 | + public void invokeAndHandle_VoidWithResponseStatus() throws Exception { |
| 67 | + Method method = on(VoidController.class).mockCall(VoidController::responseStatus).method(); |
| 68 | + HandlerResult result = invoke(new VoidController(), method).block(Duration.ZERO); |
| 69 | + |
| 70 | + assertNull("Expected no result (i.e. fully handled)", result); |
| 71 | + assertEquals(HttpStatus.BAD_REQUEST, this.exchange.getResponse().getStatusCode()); |
| 72 | + } |
| 73 | + |
| 74 | + @Test |
| 75 | + public void invokeAndHandle_withResponse() throws Exception { |
| 76 | + ServerHttpResponse response = this.exchange.getResponse(); |
| 77 | + Method method = on(VoidController.class).mockCall(c -> c.response(response)).method(); |
| 78 | + HandlerResult result = invoke(new VoidController(), method, resolverFor(Mono.just(response))) |
| 79 | + .block(Duration.ZERO); |
| 80 | + |
| 81 | + assertNull("Expected no result (i.e. fully handled)", result); |
| 82 | + assertEquals("bar", this.exchange.getResponse().getHeaders().getFirst("foo")); |
| 83 | + } |
| 84 | + |
| 85 | + @Test |
| 86 | + public void invokeAndHandle_withResponseAndMonoVoid() throws Exception { |
| 87 | + ServerHttpResponse response = this.exchange.getResponse(); |
| 88 | + Method method = on(VoidController.class).mockCall(c -> c.responseMonoVoid(response)).method(); |
| 89 | + HandlerResult result = invoke(new VoidController(), method, resolverFor(Mono.just(response))) |
| 90 | + .block(Duration.ZERO); |
| 91 | + |
| 92 | + assertNull("Expected no result (i.e. fully handled)", result); |
| 93 | + assertEquals("body", this.exchange.getResponse().getBodyAsString().block(Duration.ZERO)); |
| 94 | + } |
| 95 | + |
| 96 | + @Test |
| 97 | + public void invokeAndHandle_withExchange() throws Exception { |
| 98 | + Method method = on(VoidController.class).mockCall(c -> c.exchange(exchange)).method(); |
| 99 | + HandlerResult result = invoke(new VoidController(), method, resolverFor(Mono.just(this.exchange))) |
| 100 | + .block(Duration.ZERO); |
| 101 | + |
| 102 | + assertNull("Expected no result (i.e. fully handled)", result); |
| 103 | + assertEquals("bar", this.exchange.getResponse().getHeaders().getFirst("foo")); |
| 104 | + } |
| 105 | + |
| 106 | + @Test |
| 107 | + public void invokeAndHandle_withExchangeAndMonoVoid() throws Exception { |
| 108 | + Method method = on(VoidController.class).mockCall(c -> c.exchangeMonoVoid(exchange)).method(); |
| 109 | + HandlerResult result = invoke(new VoidController(), method, resolverFor(Mono.just(this.exchange))) |
| 110 | + .block(Duration.ZERO); |
| 111 | + |
| 112 | + assertNull("Expected no result (i.e. fully handled)", result); |
| 113 | + assertEquals("body", this.exchange.getResponse().getBodyAsString().block(Duration.ZERO)); |
| 114 | + } |
| 115 | + |
| 116 | + @Test |
| 117 | + public void invokeAndHandle_withNotModified() throws Exception { |
| 118 | + ServerWebExchange exchange = MockServerWebExchange.from( |
| 119 | + MockServerHttpRequest.get("/").ifModifiedSince(10 * 1000 * 1000)); |
| 120 | + |
| 121 | + Method method = on(VoidController.class).mockCall(c -> c.notModified(exchange)).method(); |
| 122 | + HandlerResult result = invoke(new VoidController(), method, resolverFor(Mono.just(exchange))) |
| 123 | + .block(Duration.ZERO); |
| 124 | + |
| 125 | + assertNull("Expected no result (i.e. fully handled)", result); |
| 126 | + } |
| 127 | + |
52 | 128 | @Test |
53 | 129 | public void invokeMethodWithNoArguments() throws Exception { |
54 | 130 | Method method = on(TestController.class).mockCall(TestController::noArgs).method(); |
@@ -146,7 +222,7 @@ public void invokeMethodWithResponseStatus() throws Exception { |
146 | 222 |
|
147 | 223 |
|
148 | 224 | private Mono<HandlerResult> invoke(Object handler, Method method) { |
149 | | - return this.invoke(handler, method, new HandlerMethodArgumentResolver[0]); |
| 225 | + return invoke(handler, method, new HandlerMethodArgumentResolver[0]); |
150 | 226 | } |
151 | 227 |
|
152 | 228 | private Mono<HandlerResult> invoke(Object handler, Method method, |
@@ -195,4 +271,45 @@ public String responseStatus() { |
195 | 271 | } |
196 | 272 | } |
197 | 273 |
|
| 274 | + @SuppressWarnings("unused") |
| 275 | + private static class VoidController { |
| 276 | + |
| 277 | + @ResponseStatus(HttpStatus.BAD_REQUEST) |
| 278 | + public void responseStatus() { |
| 279 | + } |
| 280 | + |
| 281 | + public void response(ServerHttpResponse response) { |
| 282 | + response.getHeaders().add("foo", "bar"); |
| 283 | + } |
| 284 | + |
| 285 | + public Mono<Void> responseMonoVoid(ServerHttpResponse response) { |
| 286 | + return response.writeWith(getBody("body")); |
| 287 | + } |
| 288 | + |
| 289 | + public void exchange(ServerWebExchange exchange) { |
| 290 | + exchange.getResponse().getHeaders().add("foo", "bar"); |
| 291 | + } |
| 292 | + |
| 293 | + public Mono<Void> exchangeMonoVoid(ServerWebExchange exchange) { |
| 294 | + return exchange.getResponse().writeWith(getBody("body")); |
| 295 | + } |
| 296 | + |
| 297 | + @Nullable |
| 298 | + public String notModified(ServerWebExchange exchange) { |
| 299 | + if (exchange.checkNotModified(Instant.ofEpochMilli(1000 * 1000))) { |
| 300 | + return null; |
| 301 | + } |
| 302 | + return "body"; |
| 303 | + } |
| 304 | + |
| 305 | + private Flux<DataBuffer> getBody(String body) { |
| 306 | + try { |
| 307 | + return Flux.just(new DefaultDataBufferFactory().wrap(body.getBytes("UTF-8"))); |
| 308 | + } |
| 309 | + catch (UnsupportedEncodingException ex) { |
| 310 | + throw new IllegalStateException(ex); |
| 311 | + } |
| 312 | + } |
| 313 | + } |
| 314 | + |
198 | 315 | } |
0 commit comments