【问题标题】:JUnit testing with spring使用 Spring 进行 JUnit 测试
【发布时间】:2011-09-23 07:41:43
【问题描述】:

我正在尝试为 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() 并检查响应。所以我不能创建一个模拟对象来传递给方法来解决这个问题。

所以我想我的问题是,是否存在一些我尚未偶然发现的配置或技巧可以让这个运行而无需重构我的控制器方法?

【问题讨论】:

    标签: java spring model-view-controller spring-mvc junit


    【解决方案1】:

    错误信息很清楚。不幸的是,您的代码需要进行一些重写。

    首先,在测试您的控制器时,您(显然)不在网络请求中。这就是RequestContextHolder.currentRequestAttributes() 不起作用的原因。但是你可以让你的测试通过重构代码,使其更具可读性,使用以下技术(假设你需要一个 HTTP 会话来从中获取一些实际属性):

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

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

    另一种解决方案是手动注册RequestScope。请参阅示例here。这应该可以在不使用模拟请求和会话修改任何代码的情况下工作。

    【讨论】:

    • 谢谢,有帮助!为了帮助澄清我为将来阅读本文的任何人解决我的问题所做的工作——我使用了@SessionAttributes("mySessionAttribute") public class AccountController { ...},我的方法最终看起来像public Response foo(@ModelAttribute("mySessionAttribute") Object myObject) {...}这是否适用于我的长期情况仍有待解决可以看到,但现在这有效。希望这对其他人有帮助。
    • 万一有人偶然发现,我找到了一个不需要重构的解决方案。做 pbdavey 在link 的帖子中提到的所有事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 2018-05-25
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多