Split tests for MethodMessageHandlers impl.
Prior to this commit, all MethodMessageHandlers tests were implemented in a single class. Since SimpAnnotationMsgHandler has been refactored with an abstract class, tests also needed such a refactoring. This commit creates test fixtures for AbstractMethodMessageHandler. Issue: SPR-11191
This commit is contained in:
parent
175aa86d79
commit
db9b6fa28e
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.messaging.handler.invocation;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.handler.DestinationPatternsMessageCondition;
|
||||
import org.springframework.messaging.handler.HandlerMethod;
|
||||
import org.springframework.messaging.handler.HandlerMethodSelector;
|
||||
import org.springframework.messaging.handler.annotation.support.MessageMethodArgumentResolver;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.messaging.support.MessageHeaderAccessor;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.ReflectionUtils.MethodFilter;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler}.
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
public class AbstractMethodMessageHandlerTests {
|
||||
|
||||
private static final String DESTINATION_HEADER = "testDestination";
|
||||
|
||||
private MyMethodMessageHandler messageHandler;
|
||||
|
||||
private TestController testController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
List<String> destinationPrefixes = new ArrayList<String>();
|
||||
destinationPrefixes.add("/test/");
|
||||
|
||||
this.messageHandler = new MyMethodMessageHandler();
|
||||
this.messageHandler.setApplicationContext(new StaticApplicationContext());
|
||||
this.messageHandler.setDestinationPrefixes(destinationPrefixes);
|
||||
this.messageHandler.afterPropertiesSet();
|
||||
this.testController = new TestController();
|
||||
this.messageHandler.registerHandler(this.testController);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void duplicateMapping() {
|
||||
this.messageHandler.registerHandler(new DuplicateMappingsController());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registeredMappings() {
|
||||
|
||||
DirectFieldAccessor fieldAccessor = new DirectFieldAccessor(this.messageHandler);
|
||||
Map<String, HandlerMethod> handlerMethods = (Map<String, HandlerMethod>)
|
||||
fieldAccessor.getPropertyValue("handlerMethods");
|
||||
|
||||
assertNotNull(handlerMethods);
|
||||
assertThat(handlerMethods.keySet(), Matchers.hasSize(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void antPatchMatchWildcard() throws Exception {
|
||||
|
||||
Method method = this.testController.getClass().getMethod("handlerPathMatchWildcard");
|
||||
this.messageHandler.registerHandlerMethod(this.testController, method, "/handlerPathMatch**");
|
||||
|
||||
MessageHeaderAccessor headers = new MessageHeaderAccessor();
|
||||
headers.setHeader(DESTINATION_HEADER, "/test/handlerPathMatchFoo");
|
||||
Message<?> message = MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build();
|
||||
this.messageHandler.handleMessage(message);
|
||||
|
||||
assertEquals("pathMatchWildcard", this.testController.method);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bestMatchWildcard() throws Exception {
|
||||
|
||||
Method method = this.testController.getClass().getMethod("bestMatch");
|
||||
this.messageHandler.registerHandlerMethod(this.testController, method, "/bestmatch/{foo}/path");
|
||||
|
||||
method = this.testController.getClass().getMethod("secondBestMatch");
|
||||
this.messageHandler.registerHandlerMethod(this.testController, method, "/bestmatch/*/*");
|
||||
|
||||
MessageHeaderAccessor headers = new MessageHeaderAccessor();
|
||||
headers.setHeader(DESTINATION_HEADER, "/test/bestmatch/bar/path");
|
||||
Message<?> message = MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build();
|
||||
this.messageHandler.handleMessage(message);
|
||||
|
||||
assertEquals("bestMatch", this.testController.method);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void argumentResolver() {
|
||||
|
||||
MessageHeaderAccessor headers = new MessageHeaderAccessor();
|
||||
headers.setHeader(DESTINATION_HEADER, "/test/handlerArgumentResolver");
|
||||
Message<?> message = MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build();
|
||||
this.messageHandler.handleMessage(message);
|
||||
|
||||
assertEquals("handlerArgumentResolver", this.testController.method);
|
||||
assertNotNull(this.testController.arguments.get("message"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionResolver() {
|
||||
|
||||
MessageHeaderAccessor headers = new MessageHeaderAccessor();
|
||||
headers.setHeader(DESTINATION_HEADER, "/test/handlerThrowsExc");
|
||||
Message<?> message = MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build();
|
||||
this.messageHandler.handleMessage(message);
|
||||
|
||||
assertEquals("illegalStateException", this.testController.method);
|
||||
assertNotNull(this.testController.arguments.get("exception"));
|
||||
|
||||
}
|
||||
|
||||
private static class TestController {
|
||||
|
||||
public String method;
|
||||
|
||||
private Map<String, Object> arguments = new LinkedHashMap<String, Object>();
|
||||
|
||||
public void handlerPathMatchWildcard() {
|
||||
this.method = "pathMatchWildcard";
|
||||
}
|
||||
|
||||
public void handlerArgumentResolver(Message message) {
|
||||
this.method = "handlerArgumentResolver";
|
||||
this.arguments.put("message", message);
|
||||
}
|
||||
|
||||
public void handlerThrowsExc() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public void bestMatch() {
|
||||
this.method = "bestMatch";
|
||||
}
|
||||
|
||||
public void secondBestMatch() {
|
||||
this.method = "secondBestMatch";
|
||||
}
|
||||
|
||||
public void illegalStateException(IllegalStateException exception) {
|
||||
this.method = "illegalStateException";
|
||||
this.arguments.put("exception", exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class DuplicateMappingsController {
|
||||
|
||||
public void handlerFoo() { }
|
||||
|
||||
public void handlerFoo(String arg) { }
|
||||
}
|
||||
|
||||
|
||||
private static class MyMethodMessageHandler extends AbstractMethodMessageHandler<String> {
|
||||
|
||||
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||
|
||||
public void registerHandler(Object handler) {
|
||||
super.detectHandlerMethods(handler);
|
||||
}
|
||||
|
||||
public void registerHandlerMethod(Object handler, Method method, String mapping) {
|
||||
super.registerHandlerMethod(handler, method, mapping);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<? extends HandlerMethodArgumentResolver> initArgumentResolvers() {
|
||||
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
|
||||
resolvers.add(new MessageMethodArgumentResolver());
|
||||
resolvers.addAll(getCustomArgumentResolvers());
|
||||
return resolvers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<? extends HandlerMethodReturnValueHandler> initReturnValueHandlers() {
|
||||
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();
|
||||
handlers.addAll(getCustomReturnValueHandlers());
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isHandler(Class<?> beanType) {
|
||||
return beanType.getName().contains("Controller");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMappingForMethod(Method method, Class<?> handlerType) {
|
||||
String methodName = method.getName();
|
||||
if(methodName.startsWith("handler")) {
|
||||
return "/" + methodName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> getDirectLookupDestinations(String mapping) {
|
||||
Set<String> result = new LinkedHashSet<String>();
|
||||
if (!this.pathMatcher.isPattern(mapping)) {
|
||||
result.add(mapping);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDestination(Message<?> message) {
|
||||
return (String) message.getHeaders().get(DESTINATION_HEADER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMatchingMapping(String mapping, Message<?> message) {
|
||||
|
||||
String destination = getLookupDestination(getDestination(message));
|
||||
if(mapping.equals(destination) || this.pathMatcher.match(mapping, destination)) {
|
||||
return mapping;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Comparator<String> getMappingComparator(Message<?> message) {
|
||||
return new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String info1, String info2) {
|
||||
DestinationPatternsMessageCondition cond1 = new DestinationPatternsMessageCondition(info1);
|
||||
DestinationPatternsMessageCondition cond2 = new DestinationPatternsMessageCondition(info2);
|
||||
return cond1.compareTo(cond2, message);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractExceptionHandlerMethodResolver createExceptionHandlerMethodResolverFor(Class<?> beanType) {
|
||||
return new MyExceptionHandlerMethodResolver(beanType);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyExceptionHandlerMethodResolver extends AbstractExceptionHandlerMethodResolver {
|
||||
|
||||
public MyExceptionHandlerMethodResolver(Class<?> handlerType) {
|
||||
super(initExceptionMappings(handlerType));
|
||||
}
|
||||
|
||||
private static Map<Class<? extends Throwable>, Method> initExceptionMappings(Class<?> handlerType) {
|
||||
Map<Class<? extends Throwable>, Method> result = new HashMap<Class<? extends Throwable>, Method>();
|
||||
for (Method method : HandlerMethodSelector.selectMethods(handlerType, EXCEPTION_HANDLER_METHOD_FILTER)) {
|
||||
for(Class<? extends Throwable> exception : getExceptionsFromMethodSignature(method)) {
|
||||
result.put(exception, method);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public final static MethodFilter EXCEPTION_HANDLER_METHOD_FILTER = new MethodFilter() {
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method) {
|
||||
return method.getName().contains("Exception");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -82,11 +82,6 @@ public class SimpAnnotationMethodMessageHandlerTests {
|
|||
assertEquals("bar", ((Map<String, Object>) this.testController.arguments.get("headers")).get("foo"));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void duplicateMappings() {
|
||||
this.messageHandler.registerHandler(new DuplicateMappingController());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messageMappingDestinationVariableResolution() {
|
||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create();
|
||||
|
@ -112,27 +107,6 @@ public class SimpAnnotationMethodMessageHandlerTests {
|
|||
assertEquals("value", this.testController.arguments.get("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void antPatchMatchWildcard() {
|
||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create();
|
||||
headers.setDestination("/pre/pathmatch/wildcard/test");
|
||||
Message<?> message = MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build();
|
||||
this.messageHandler.handleMessage(message);
|
||||
|
||||
assertEquals("pathMatchWildcard", this.testController.method);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bestMatchWildcard() {
|
||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
|
||||
headers.setDestination("/pre/bestmatch/bar/path");
|
||||
Message<?> message = MessageBuilder.withPayload(new byte[0]).setHeaders(headers).build();
|
||||
this.messageHandler.handleMessage(message);
|
||||
|
||||
assertEquals("bestMatch", this.testController.method);
|
||||
assertEquals("bar", this.testController.arguments.get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleBinding() {
|
||||
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create();
|
||||
|
@ -201,22 +175,6 @@ public class SimpAnnotationMethodMessageHandlerTests {
|
|||
this.arguments.put("name", param2);
|
||||
}
|
||||
|
||||
@MessageMapping("/pathmatch/wildcard/**")
|
||||
public void pathMatchWildcard() {
|
||||
this.method = "pathMatchWildcard";
|
||||
}
|
||||
|
||||
@MessageMapping("/bestmatch/{foo}/path")
|
||||
public void bestMatch(@DestinationVariable("foo") String param1) {
|
||||
this.method = "bestMatch";
|
||||
this.arguments.put("foo", param1);
|
||||
}
|
||||
|
||||
@MessageMapping("/bestmatch/*/*")
|
||||
public void secondBestMatch() {
|
||||
this.method = "secondBestMatch";
|
||||
}
|
||||
|
||||
@MessageMapping("/binding/id/{id}")
|
||||
public void simpleBinding(@DestinationVariable("id") Long id) {
|
||||
this.method = "simpleBinding";
|
||||
|
@ -235,16 +193,6 @@ public class SimpAnnotationMethodMessageHandlerTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Controller
|
||||
private static class DuplicateMappingController {
|
||||
|
||||
@MessageMapping(value="/duplicate")
|
||||
public void handle1() { }
|
||||
|
||||
@MessageMapping(value="/duplicate")
|
||||
public void handle2() { }
|
||||
}
|
||||
|
||||
private static class StringNotEmptyValidator implements Validator {
|
||||
@Override
|
||||
public boolean supports(Class<?> clazz) {
|
||||
|
|
Loading…
Reference in New Issue