diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/result/HandlerResultMatchers.java b/spring-test/src/main/java/org/springframework/test/web/servlet/result/HandlerResultMatchers.java index 591eeb8cb20..cc55e188072 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/result/HandlerResultMatchers.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/result/HandlerResultMatchers.java @@ -25,12 +25,14 @@ import org.springframework.test.web.servlet.ResultMatcher; import org.springframework.util.ClassUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; +import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.MethodInvocationInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import static org.hamcrest.MatcherAssert.assertThat; import static org.springframework.test.util.AssertionErrors.assertEquals; import static org.springframework.test.util.AssertionErrors.assertTrue; +import static org.springframework.test.util.AssertionErrors.fail; /** * Factory for assertions on the selected handler or handler method. @@ -43,6 +45,7 @@ import static org.springframework.test.util.AssertionErrors.assertTrue; * which is used by default with the Spring MVC Java config and XML namespace. * * @author Rossen Stoyanchev + * @author Sam Brannen * @since 3.2 */ public class HandlerResultMatchers { @@ -75,13 +78,13 @@ public class HandlerResultMatchers { } /** - * Assert the controller method used to process the request. The expected - * method is specified through a "mock" controller method invocation - * similar to {@link MvcUriComponentsBuilder#fromMethodCall(Object)}. - *

For example given this controller: + * Assert the controller method used to process the request. + *

The expected method is specified through a "mock" controller method + * invocation similar to {@link MvcUriComponentsBuilder#fromMethodCall(Object)}. + *

For example, given this controller: *

 	 * @RestController
-	 * static class SimpleController {
+	 * public class SimpleController {
 	 *
 	 *     @RequestMapping("/")
 	 *     public ResponseEntity handle() {
@@ -89,19 +92,29 @@ public class HandlerResultMatchers {
 	 *     }
 	 * }
 	 * 
- *

A test can be performed: + *

A test that has statically imported {@link MvcUriComponentsBuilder#on} + * can be performed as follows: *

 	 * mockMvc.perform(get("/"))
 	 *     .andExpect(handler().methodCall(on(SimpleController.class).handle()));
 	 * 
+ * + * @param obj either the value returned from a "mock" controller invocation + * or the "mock" controller itself after an invocation */ - public ResultMatcher methodCall(final Object info) { + public ResultMatcher methodCall(final Object obj) { return new ResultMatcher() { @Override public void match(MvcResult result) throws Exception { - HandlerMethod handlerMethod = getHandlerMethod(result); - Method method = ((MvcUriComponentsBuilder.MethodInvocationInfo) info).getControllerMethod(); - assertEquals("HandlerMethod", method, handlerMethod.getMethod()); + if (!MethodInvocationInfo.class.isInstance(obj)) { + fail(String.format("The supplied object [%s] is not an instance of %s. " + + "Ensure that you invoke the handler method via MvcUriComponentsBuilder.on().", + obj, MethodInvocationInfo.class.getName())); + } + MethodInvocationInfo invocationInfo = (MethodInvocationInfo) obj; + Method expected = invocationInfo.getControllerMethod(); + Method actual = getHandlerMethod(result).getMethod(); + assertEquals("Handler method", expected, actual); } }; } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HandlerAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HandlerAssertionTests.java index a17e7c02b96..2c671bbf655 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HandlerAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HandlerAssertionTests.java @@ -18,7 +18,9 @@ package org.springframework.test.web.servlet.samples.standalone.resultmatchers; import java.lang.reflect.Method; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.springframework.http.ResponseEntity; import org.springframework.test.web.servlet.MockMvc; @@ -39,11 +41,14 @@ import static org.springframework.web.servlet.mvc.method.annotation.MvcUriCompon * Examples of expectations on the controller type and controller method. * * @author Rossen Stoyanchev + * @author Sam Brannen */ public class HandlerAssertionTests { private final MockMvc mockMvc = standaloneSetup(new SimpleController()).alwaysExpect(status().isOk()).build(); + @Rule + public final ExpectedException exception = ExpectedException.none(); @Test @@ -52,6 +57,15 @@ public class HandlerAssertionTests { } @Test + public void methodCallOnNonMock() throws Exception { + exception.expect(AssertionError.class); + exception.expectMessage("The supplied object [bogus] is not an instance of"); + exception.expectMessage(MvcUriComponentsBuilder.MethodInvocationInfo.class.getName()); + exception.expectMessage("Ensure that you invoke the handler method via MvcUriComponentsBuilder.on()"); + + this.mockMvc.perform(get("/")).andExpect(handler().methodCall("bogus")); + } + @Test public void methodCall() throws Exception { this.mockMvc.perform(get("/")).andExpect(handler().methodCall(on(SimpleController.class).handle()));