I have a simple annotated controller similar to this one:
@Controller
public class MyController {
@RequestMapping("/{id}.html")
public String doSomething(@PathVariable String id, Model model) {
// do something
return "view";
}
}
and I want to test it with an unit test like this:
public class MyControllerTest {
@Test
public void test() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/test.html");
new AnnotationMethodHandlerAdapter()
.handle(request, new MockHttpServletResponse(), new MyController());
// assert something
}
}
The problem is that AnnotationMethodHandlerAdapter.handler() method throws an exception:
java.lang.IllegalStateException: Could not find @PathVariable [id] in @RequestMapping
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.resolvePathVariable(AnnotationMethodHandlerAdapter.java:642)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolvePathVariable(HandlerMethodInvoker.java:514)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:262)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:146)
As of Spring 3.2, there is a proper way to test this, in an elegant and easy way. You will be able to do things like this:
For further information, take a look at http://blog.springsource.org/2012/11/12/spring-framework-3-2-rc1-spring-mvc-test-framework/
I'm not sure my original answer is going to help with @PathVariable. I've just tried testing an @PathVariable and I get the following exception:
org.springframework.web.bind.annotation.support.HandlerMethodInvocationException: Failed to invoke handler method [public org.springframework.web.servlet.ModelAndView test.MyClass.myMethod(test.SomeType)]; nested exception is java.lang.IllegalStateException: Could not find @PathVariable [parameterName] in @RequestMapping
The reason is that the path variables in the request get parsed by an interceptor. The following approach works for me:
I've add a new blog post on integration testing spring mvc annotations
I'd call what you're after an integration test based on the terminology in the Spring reference manual. How about doing something like:
For more information I've written a blog entry about integration testing Spring MVC annotations.
A promising framework for testing Spring MVC https://github.com/SpringSource/spring-test-mvc
Provided you are using Spring 3.0.x.
Here I suggest a merger of Emil and scarba05 answers using spring-test not spring-test-mvc. Please skip this answer and refer to spring-test-mvc examples if you are using Spring 3.2.x or later
MyControllerWithParameter.java
MyControllerTest.java
}
The exception message refers to a "feed" variable, which isn't present in your sample code, it's likely being caused by something you haven't shown us.
Also, your test is testing Spring and your own code. Is this really what you want to do?
It's better to assume that Spring works (which it does), and just test your own class, i.e. call
MyController.doSomething()
directly. That's one benefit of the annotation approach - you don't need to use mock requests and responses, you just use domain POJOs.