Java Spring 3.2:@Scope(“请求”)的单元测试不再有效
在Spring 3.1中,如果我包含以下BeanFactoryPostProcessor,我可以将具有`@Scope(“request”)的Jax RS资源自动连接到我的单元测试中:Java Spring 3.2:@Scope(“请求”)的单元测试不再有效,java,spring,unit-testing,jax-rs,Java,Spring,Unit Testing,Jax Rs,在Spring 3.1中,如果我包含以下BeanFactoryPostProcessor,我可以将具有`@Scope(“request”)的Jax RS资源自动连接到我的单元测试中: @Component public class MockRequestBeanFactoryPostProcessor implements BeanFactoryPostProcessor { public void postProcessBeanFactory( ConfigurableLis
@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);
}
}
在Spring3.2中,运行的第一个测试方法是有效的,但是所有后续的测试方法都是有效的
java.lang.IllegalStateException:未找到线程绑定请求:您是指实际web请求之外的请求属性,还是在原始接收线程之外处理请求?如果您实际上在web请求中操作,并且仍然收到此消息,那么您的代码可能在DispatcherServlet/DispatcherPortlet之外运行:在这种情况下,请使用RequestContextListener或RequestContextFilter公开当前请求
如何使测试重新工作?BeanFactoryPostProcessor有缺陷,它只运行一次,因此只有一个线程具有(不可重用的)
MockHttpServletRequest
移动创建请求并将其存储在RequestContextHolder
中的代码时,应将其移动到
注释方法,而在@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
Spring3.2引入了ServletTestExecutionListener
,它粗暴地将自己注入到旧的测试中
其javadoc:
TestExecutionListener,它为SpringTestContext框架加载的WebApplicationContext提供模拟Servlet API支持
具体来说,ServletTestExecutionListener在测试实例准备期间和每个测试方法之前通过SpringWeb的RequestContextHolder设置线程本地状态,并基于WebApplicationContext中的MockServletContext创建MockHttpServletRequest、MockHttpServletResponse和ServletWebRequest。此侦听器还确保可以将MockHttpServletResponse和ServletWebRequest注入测试实例,测试完成后,此侦听器将清除线程本地状态
请注意,默认情况下已启用ServletTestExecutionListener,但如果为当前测试加载的ApplicationContext不是WebApplicationContext,则不会采取任何操作
问题是最后一段是谎言。诚然,除非您进行配置更改,否则该类不会开始帮助您,但无论发生什么情况,它都会在每次测试后愉快地重置请求
可以通过向测试类添加@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
来禁用侦听器。(您可能需要根据需要编辑的实际侦听器集。)
或者,您可以设置
@WebAppConfiguration
并删除MockRequestBeanFactoryPostProcessor以及其他遗留解决方案,如MockServletContextawareReprocessor。这不起作用,因为在调用方法之前,Spring会在@之前自动连接我的测试类。您可以改为执行查找。您可以添加/尝试的另一件事是将@WebAppConfiguration
注释添加到您的测试类中(我假设您正在使用Springs测试支持来加载和自动连接)。这将消除对BeanFactoryPostProcessor
和@Before
/@After
方法的需要。请添加您的测试类。我将使用默认值并放弃解决方法(需要维护的代码更少:))。很好地捕捉到了重置,您可能需要为此注册一个bug/enhanchement。@M.Deinum事情是,根据,我对ServletContext和单元测试做了一些有趣的事情。我需要设置资源路径,但是@WebAppConfiguration.value
在编译时得到修复。因此,我想我会继续使用我的自定义ServletContextaware。在任何情况下,当我手动运行junit(通过JUnitCore编程)时,内置的SCAP都无法工作(@WAC
bug?),因此我别无选择。但是我似乎可以同时使用@WAC
和我的自定义SCAP,同时跳过RequestBeanFactoryPostProcessor
。