JUnit testing with spring
I am trying to create a junit test for a spring controller method but I keep receiving the following error
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request,
or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message,
your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:123)
I have added both the things it tells me I need (I've tried each one separately) and currently my web.xml contains
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<filter>
<filter-name>requestContextFi开发者_JAVA百科lter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
and the method I'm trying to test is something along the lines of
@Controller
@RemotingDestination
public class MyController {
public Response foo()
{
//...
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpSession httpSession = attr.getRequest().getSession(true);
//...
}
and my junit test simply calls myController.foo() and checks the reponse. So I can't create a mock object to pass into the method to get around this issue.
So I suppose my question is, does there exist some configuration or trick that I have yet to stumble upon that will make this run without having to refactor my controller method?
The error message is pretty clear. Unfortunately your code requires a bit of a rewrite.
First of all while testing your controller you (obviously) are not inside a web request. That's why RequestContextHolder.currentRequestAttributes()
does not work. But you can make your test to pass and refactor the code to be much more readable using the following technique (assuming you need an HTTP session to get some actual attribute from it):
public Response foo(@SessionAttribute("someSessionAttribute") int id)
This way Spring MVC will automatically fetch the session and load someSessionAttribute
when inside a web request (and even perform required conversion). But when you are testing the controller, just call the method with fixed parameter. No request/session infrastructure code. Much cleaner (note that the two lines in foo
you've provided aren't needed at all).
The other solution is to register RequestScope
manually. See example here. This should work without modifying any of your code with mocked request and session.
精彩评论