2011-09-23 130 views
2

我正在尝试为spring控制器方法创建一个junit测试,但我一直收到以下错误使用spring进行JUnit测试

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) 

我已经添加了它告诉我需要的东西(我已经分别尝试了每个)并且目前我的web.xml包含

<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>requestContextFilter</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> 

,我正在尝试测试的方法是

@Controller 
@RemotingDestination 
public class MyController { 

public Response foo() 
    { 
//... 
     ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); 
     HttpSession httpSession = attr.getRequest().getSession(true); 
//... 
} 

,我的junit测试只需调用myController.foo()并检查响应。所以我无法创建一个模拟对象来传递给方法来解决这个问题。

所以我想我的问题是,是否存在一些我尚未偶然发现的配置或技巧,这将使得运行而不必重构我的控制器方法?

回答

3

错误信息非常清楚。不幸的是,你的代码需要一些重写。

首先,在测试你的控制器的时候你显然不在web请求中。这就是为什么RequestContextHolder.currentRequestAttributes()不起作用。但是你可以让你的测试通过重构代码是更具可读性使用以下方法(假设你需要一个HTTP会话,从它那里得到一些实际的属性):

public Response foo(@SessionAttribute("someSessionAttribute") int id) 

这样的Spring MVC将在网络请求中自动获取会话并加载someSessionAttribute(甚至执行所需的转换)。但是,当您测试控制器时,只需使用固定参数调用该方法即可。没有请求/会话基础结构代码。更清洁(请注意,您提供的foo中的两行根本不需要)。

另一种解决方法是手动注册RequestScope。见示例here。这应该不会修改任何代码与嘲笑的请求和会话。

+0

+1顺便说一句,你需要在示例代码中添加一个类型。 –

+0

谢谢,更正! –

+0

谢谢,这有帮助!为了帮助澄清我为解决未来读者的问题所做的工作 - 我使用了@SessionAttributes(“mySessionAttribute”)public class AccountController {...}',我的方法看起来像'public Response foo (@ModelAttribute(“mySessionAttribute”)Object myObject){...}' 这是否适用于我的情况在长期内仍有待观察,但现在这是有效的。希望这可以帮助别人。 – user960564