使用 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() 并检查响应。因此,我无法创建模拟对象来传递到方法中来解决此问题。
所以我想我的问题是,是否存在一些我尚未偶然发现的配置或技巧可以使此运行而无需重构我的控制器方法?
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>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>
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
错误信息非常清楚。不幸的是,您的代码需要进行一些重写。
首先,在测试您的控制器时,您(显然)不在网络请求中。这就是
RequestContextHolder.currentRequestAttributes()
不起作用的原因。但是您可以使用以下技术使您的测试通过并重构代码以使其更具可读性(假设您需要一个 HTTP 会话来从中获取一些实际属性):这样 Spring MVC 将自动在 Web 请求中获取会话并加载
someSessionAttribute
(甚至执行所需的转换)。但是当你测试控制器时,只需调用具有固定参数的方法即可。没有请求/会话基础设施代码。更加清晰(请注意,您提供的 foo 中的两行根本不需要)。另一种解决方案是手动注册
RequestScope
。请参阅此处的示例。这应该可以工作,而无需使用模拟请求和会话修改任何代码。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):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 infoo
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.