Spring 3.2:@Scope(“请求”)的单元测试不再有效

时间:2013-12-03 09:03:50

标签: java spring unit-testing jax-rs

在Spring 3.1中,我可以将一个带有@Scope(“request”)的Jax-RS资源自动装入我的单元测试中,前提是我包含了以下BeanFactoryPostProcessor:

@Component
public class MockRequestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

public void postProcessBeanFactory(
        ConfigurableListableBeanFactory beanFactory) throws BeansException {

    beanFactory.registerScope("request", new RequestScope());
    MockHttpServletRequest request = new MockHttpServletRequest();
    ServletRequestAttributes attributes = new ServletRequestAttributes(request);
    RequestContextHolder.setRequestAttributes(attributes);
}

}

使用Spring 3.2,第一个运行的测试方法可行,但所有后续测试方法都可以

  

java.lang.IllegalStateException:找不到线程绑定请求:您是指实际Web请求之外的请求属性,还是处理最初接收线程之外的请求?如果您实际上是在Web请求中操作并仍然收到此消息,则您的代码可能在DispatcherServlet / DispatcherPortlet之外运行:在这种情况下,请使用RequestContextListener或RequestContextFilter来公开当前请求。

如何让我的测试再次运行?

2 个答案:

答案 0 :(得分:3)

BeanFactoryPostProcessor存在缺陷,它只运行一次,因此只有一个线程会有(不可重复使用)MockHttpServletRequest

移动创建请求并将其存储在RequestContextHolder中的代码应移至@Before带注释的方法,并在@After带注释的方法中清除RequestContextHolder }。

@Before
public void init() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    ServletRequestAttributes attributes = new ServletRequestAttributes(request);
    RequestContextHolder.setRequestAttributes(attributes);
}

@After
public void cleanUp() {
    RequestContextHolder.resetRequestAttributes();
}

您仍然需要BeanFactoryPostProcessor才能注册RequestScope

答案 1 :(得分:0)

Spring 3.2引入了ServletTestExecutionListener,它粗暴地为你的旧测试注入了自己。

它的javadoc:

  

TestExecutionListener,它为Spring TestContext Framework加载的WebApplicationContexts提供模拟Servlet API支持。

     

具体来说,ServletTestExecutionListener在测试实例准备期间和每个测试方法之前通过Spring Web的RequestContextHolder设置线程本地状态,并根据WebApplicationContext中存在的MockServletContext创建MockHttpServletRequest,MockHttpServletResponse和ServletWebRequest。此侦听器还确保可以将MockHttpServletResponse和ServletWebRequest注入到测试实例中,并且一旦测试完成,此侦听器就会清除线程本地状态。

     

请注意,默认情况下启用ServletTestExecutionListener,但如果为当前测试加载的ApplicationContext不是WebApplicationContext,则不执行任何操作。

问题是最后一段是谎言。没错,除非您进行配置更改,否则此类不会开始帮助您,但无论如何,它都会在每次测试后愉快地重置请求。

可以通过将@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class })添加到测试类来禁用侦听器。 (您可能需要根据需要编辑的实际侦听器集。)

或者,您可以设置@WebAppConfiguration并删除MockRequestBeanFactoryPostProcessor以及其他遗留解决方法,如MockServletContextAwareProcessor。