@ -16,26 +16,40 @@
@@ -16,26 +16,40 @@
package org.springframework.web.reactive.result.method ;
import java.io.UnsupportedEncodingException ;
import java.lang.reflect.Method ;
import java.time.Duration ;
import java.time.Instant ;
import java.util.Arrays ;
import org.junit.Test ;
import reactor.core.publisher.Flux ;
import reactor.core.publisher.Mono ;
import reactor.test.StepVerifier ;
import org.springframework.core.io.buffer.DataBuffer ;
import org.springframework.core.io.buffer.DefaultDataBufferFactory ;
import org.springframework.http.HttpStatus ;
import org.springframework.http.server.reactive.ServerHttpResponse ;
import org.springframework.lang.Nullable ;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest ;
import org.springframework.mock.web.test.server.MockServerWebExchange ;
import org.springframework.web.bind.annotation.ResponseStatus ;
import org.springframework.web.reactive.BindingContext ;
import org.springframework.web.reactive.HandlerResult ;
import org.springframework.web.server.ServerWebExchange ;
import org.springframework.web.server.UnsupportedMediaTypeStatusException ;
import static org.hamcrest.Matchers.* ;
import static org.junit.Assert.* ;
import static org.hamcrest.Matchers.is ;
import static org.junit.Assert.assertEquals ;
import static org.junit.Assert.assertNull ;
import static org.junit.Assert.assertThat ;
import static org.junit.Assert.fail ;
import static org.mockito.Mockito.any ;
import static org.mockito.Mockito.* ;
import static org.springframework.web.method.ResolvableMethod.* ;
import static org.mockito.Mockito.mock ;
import static org.mockito.Mockito.when ;
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get ;
import static org.springframework.web.method.ResolvableMethod.on ;
/ * *
* Unit tests for { @link InvocableHandlerMethod } .
@ -45,10 +59,72 @@ import static org.springframework.web.method.ResolvableMethod.*;
@@ -45,10 +59,72 @@ import static org.springframework.web.method.ResolvableMethod.*;
* /
public class InvocableHandlerMethodTests {
private final MockServerWebExchange exchange =
MockServerWebExchange . from ( MockServerHttpRequest . get ( "http://localhost:8080/path" ) ) ;
private final MockServerWebExchange exchange = MockServerWebExchange . from ( get ( "http://localhost:8080/path" ) ) ;
@Test
public void invokeAndHandle_VoidWithResponseStatus ( ) throws Exception {
Method method = on ( VoidController . class ) . mockCall ( VoidController : : responseStatus ) . method ( ) ;
HandlerResult result = invoke ( new VoidController ( ) , method ) . block ( Duration . ZERO ) ;
assertNull ( "Expected no result (i.e. fully handled)" , result ) ;
assertEquals ( HttpStatus . BAD_REQUEST , this . exchange . getResponse ( ) . getStatusCode ( ) ) ;
}
@Test
public void invokeAndHandle_withResponse ( ) throws Exception {
ServerHttpResponse response = this . exchange . getResponse ( ) ;
Method method = on ( VoidController . class ) . mockCall ( c - > c . response ( response ) ) . method ( ) ;
HandlerResult result = invoke ( new VoidController ( ) , method , resolverFor ( Mono . just ( response ) ) )
. block ( Duration . ZERO ) ;
assertNull ( "Expected no result (i.e. fully handled)" , result ) ;
assertEquals ( "bar" , this . exchange . getResponse ( ) . getHeaders ( ) . getFirst ( "foo" ) ) ;
}
@Test
public void invokeAndHandle_withResponseAndMonoVoid ( ) throws Exception {
ServerHttpResponse response = this . exchange . getResponse ( ) ;
Method method = on ( VoidController . class ) . mockCall ( c - > c . responseMonoVoid ( response ) ) . method ( ) ;
HandlerResult result = invoke ( new VoidController ( ) , method , resolverFor ( Mono . just ( response ) ) )
. block ( Duration . ZERO ) ;
assertNull ( "Expected no result (i.e. fully handled)" , result ) ;
assertEquals ( "body" , this . exchange . getResponse ( ) . getBodyAsString ( ) . block ( Duration . ZERO ) ) ;
}
@Test
public void invokeAndHandle_withExchange ( ) throws Exception {
Method method = on ( VoidController . class ) . mockCall ( c - > c . exchange ( exchange ) ) . method ( ) ;
HandlerResult result = invoke ( new VoidController ( ) , method , resolverFor ( Mono . just ( this . exchange ) ) )
. block ( Duration . ZERO ) ;
assertNull ( "Expected no result (i.e. fully handled)" , result ) ;
assertEquals ( "bar" , this . exchange . getResponse ( ) . getHeaders ( ) . getFirst ( "foo" ) ) ;
}
@Test
public void invokeAndHandle_withExchangeAndMonoVoid ( ) throws Exception {
Method method = on ( VoidController . class ) . mockCall ( c - > c . exchangeMonoVoid ( exchange ) ) . method ( ) ;
HandlerResult result = invoke ( new VoidController ( ) , method , resolverFor ( Mono . just ( this . exchange ) ) )
. block ( Duration . ZERO ) ;
assertNull ( "Expected no result (i.e. fully handled)" , result ) ;
assertEquals ( "body" , this . exchange . getResponse ( ) . getBodyAsString ( ) . block ( Duration . ZERO ) ) ;
}
@Test
public void invokeAndHandle_withNotModified ( ) throws Exception {
ServerWebExchange exchange = MockServerWebExchange . from (
MockServerHttpRequest . get ( "/" ) . ifModifiedSince ( 10 * 1000 * 1000 ) ) ;
Method method = on ( VoidController . class ) . mockCall ( c - > c . notModified ( exchange ) ) . method ( ) ;
HandlerResult result = invoke ( new VoidController ( ) , method , resolverFor ( Mono . just ( exchange ) ) )
. block ( Duration . ZERO ) ;
assertNull ( "Expected no result (i.e. fully handled)" , result ) ;
}
@Test
public void invokeMethodWithNoArguments ( ) throws Exception {
Method method = on ( TestController . class ) . mockCall ( TestController : : noArgs ) . method ( ) ;
@ -146,7 +222,7 @@ public class InvocableHandlerMethodTests {
@@ -146,7 +222,7 @@ public class InvocableHandlerMethodTests {
private Mono < HandlerResult > invoke ( Object handler , Method method ) {
return this . invoke ( handler , method , new HandlerMethodArgumentResolver [ 0 ] ) ;
return invoke ( handler , method , new HandlerMethodArgumentResolver [ 0 ] ) ;
}
private Mono < HandlerResult > invoke ( Object handler , Method method ,
@ -195,4 +271,45 @@ public class InvocableHandlerMethodTests {
@@ -195,4 +271,45 @@ public class InvocableHandlerMethodTests {
}
}
@SuppressWarnings ( "unused" )
private static class VoidController {
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public void responseStatus ( ) {
}
public void response ( ServerHttpResponse response ) {
response . getHeaders ( ) . add ( "foo" , "bar" ) ;
}
public Mono < Void > responseMonoVoid ( ServerHttpResponse response ) {
return response . writeWith ( getBody ( "body" ) ) ;
}
public void exchange ( ServerWebExchange exchange ) {
exchange . getResponse ( ) . getHeaders ( ) . add ( "foo" , "bar" ) ;
}
public Mono < Void > exchangeMonoVoid ( ServerWebExchange exchange ) {
return exchange . getResponse ( ) . writeWith ( getBody ( "body" ) ) ;
}
@Nullable
public String notModified ( ServerWebExchange exchange ) {
if ( exchange . checkNotModified ( Instant . ofEpochMilli ( 1000 * 1000 ) ) ) {
return null ;
}
return "body" ;
}
private Flux < DataBuffer > getBody ( String body ) {
try {
return Flux . just ( new DefaultDataBufferFactory ( ) . wrap ( body . getBytes ( "UTF-8" ) ) ) ;
}
catch ( UnsupportedEncodingException ex ) {
throw new IllegalStateException ( ex ) ;
}
}
}
}