简体   繁体   English

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

[英]Spring 3.2: Unit testing of @Scope(“request”) no longer works

In Spring 3.1, I could autowire a Jax-RS resource that had `@Scope("request") into my unit tests provided I included the following BeanFactoryPostProcessor: 在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);
}

} }

With Spring 3.2, the first test method that runs works, but all subsequent test methods get 使用Spring 3.2,第一个运行的测试方法可行,但所有后续测试方法都可以实现

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

How can I get my tests working again? 我怎样才能让我的测试再次运行?

The BeanFactoryPostProcessor is flawed, it runs only once and so only a single thread will have a (not reusable) MockHttpServletRequest . BeanFactoryPostProcessor存在缺陷,它只运行一次,因此只有一个线程将具有(不可重用) MockHttpServletRequest

Moving the code which creates the request and stores it in the RequestContextHolder should be moved to a @Before annotated method and in an @After annotated method you should cleanup the RequestContextHolder . 移动它创建请求,并将其存储在所述代码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();
}

You still need the BeanFactoryPostProcessor to register the RequestScope . 您仍然需要BeanFactoryPostProcessor来注册RequestScope

Spring 3.2 introduced the ServletTestExecutionListener , which rudely injects itself into your old tests. Spring 3.2引入了ServletTestExecutionListener ,它粗暴地将自己注入到旧的测试中。

Its javadoc: 它的javadoc:

TestExecutionListener which provides mock Servlet API support to WebApplicationContexts loaded by the Spring TestContext Framework. TestExecutionListener,它为Spring TestContext Framework加载的WebApplicationContexts提供模拟Servlet API支持。

Specifically, ServletTestExecutionListener sets up thread-local state via Spring Web's RequestContextHolder during test instance preparation and before each test method and creates a MockHttpServletRequest, MockHttpServletResponse, and ServletWebRequest based on the MockServletContext present in the WebApplicationContext. 具体来说,ServletTestExecutionListener在测试实例准备期间和每个测试方法之前通过Spring Web的RequestContextHolder设置线程本地状态,并基于WebApplicationContext中存在的MockServletContext创建MockHttpServletRequest,MockHttpServletResponse和ServletWebRequest。 This listener also ensures that the MockHttpServletResponse and ServletWebRequest can be injected into the test instance, and once the test is complete this listener cleans up thread-local state. 此侦听器还确保可以将MockHttpServletResponse和ServletWebRequest注入到测试实例中,并且一旦测试完成,此侦听器就会清除线程本地状态。

Note that ServletTestExecutionListener is enabled by default but takes no action if the ApplicationContext loaded for the current test is not a WebApplicationContext. 请注意,默认情况下启用ServletTestExecutionListener,但如果为当前测试加载的ApplicationContext不是WebApplicationContext,则不执行任何操作。

The problem is that the last paragraph is a lie. 问题是最后一段是谎言。 True, this class doesn't start helping you unless you make configuration changes, but it will gleefully reset the request after each test, no matter what. 没错,除非您进行配置更改,否则此类不会开始帮助您,但无论如何,它都会在每次测试后愉快地重置请求。

The listener can be disabled by adding @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class }) to the test class. 可以通过将@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class })到测试类来禁用侦听器。 (The actual set of listeners you may want to edit as needed.) (您可能需要根据需要编辑的实际侦听器集。)

Alternatively, you can set @WebAppConfiguration and remove the MockRequestBeanFactoryPostProcessor as well other legacy work-arounds like the MockServletContextAwareProcessor. 或者,您可以设置@WebAppConfiguration并删除MockRequestBeanFactoryPostProcessor以及其他遗留解决方法,如MockServletContextAwareProcessor。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM