spring测试中的java请求范围bean
我想在我的应用程序中使用请求范围的bean。我使用JUnit4进行测试。如果我尝试在这样的测试中创建一个:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/TestScopedBeans-context.xml" })
public class TestScopedBeans {
protected final static Logger logger = Logger
.getLogger(TestScopedBeans.class);
@Resource
private Object tObj;
@Test
public void testBean() {
logger.debug(tObj);
}
@Test
public void testBean2() {
logger.debug(tObj);
}
使用以下bean定义:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="java.lang.Object" id="tObj" scope="request" />
</beans>
我得到:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gov.nasa.arc.cx.sor.query.TestScopedBeans': Injection of resource fields failed; nested exception is java.lang.IllegalStateException: No Scope registered for scope 'request'
<...SNIP...>
Caused by: java.lang.IllegalStateException: No Scope registered for scope 'request'
所以我发现这个博客似乎很有帮助: http://www.javathinking.com/2009/06/no-scope-registered-for-scope-request_5.html
但是我注意到他使用了AbstractDependencyInjectionSpringContextTests,这在Spring3.0中似乎被弃用了。 此时我使用Spring2.5,但我认为将此方法转换为使用AbstractJUnit4SpringContextTests应该不会太难 正如文档所建议的(好的,文档链接到3.8版本,但我使用的是4.4)。所以我改变了主意 测试以扩展AbstractJUnit4SpringContextTests。。。同样的信息。同样的问题。现在是我想要的prepareTestInstance()方法 未定义要覆盖的对象。好吧,也许我会把那些登记镜电话放在别的地方。。。所以我读了更多关于TestExecutionListeners的书,认为这样会更好,因为我不想继承spring包结构。所以 我将测试更改为:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/TestScopedBeans-context.xml" })
@TestExecutionListeners({})
public class TestScopedBeans {
我希望我必须创建一个自定义侦听器,但当我运行它时,我忘记了。它起作用了!很好,但是为什么呢?我看不出有哪位股票听众 正在注册请求范围或会话范围,为什么要注册?现在还没有什么要说的,这可能不是对SpringMVC代码的测试
# 1 楼答案
Spring 3.2或更新版本的解决方案
Spring从版本3.2provides support for session/request scoped beans for integration testing开始强>
阅读更多:Request and Session Scoped Beans
3.2之前的Spring解决方案,带listener
WebContextTestExecutionListener.java
Spring 3.2之前的解决方案,具有自定义范围
TestConfig.java
或者使用xml配置
test-config.xml
源代码
提供的所有解决方案的源代码:
# 2 楼答案
我尝试过几种解决方案,包括@Marius的带有“WebContextTestExecutionListener”的解决方案,但对我来说不起作用,因为这段代码在创建请求范围之前加载了应用程序上下文
最终帮助我的答案并不是一个新的答案,但很好: http://tarunsapra.wordpress.com/2011/06/28/junit-spring-session-and-request-scope-beans/
我只是将以下代码段添加到我的(测试)应用程序上下文中:
祝你好运
# 3 楼答案
Test Request-Scoped Beans with Spring很好地解释了如何使用Spring注册和创建自定义范围
简而言之,正如Ido Cohn所解释的,在文本上下文配置中添加以下内容就足够了:
与使用基于ThreadLocal的预定义SimpleThreadScope不同,实现自定义SimpleThreadScope也很容易,如本文所述
# 4 楼答案
使用Spring4测试的解决方案,用于当您需要请求范围的bean但不通过
MockMVC
等发出任何请求时# 5 楼答案
测试通过,因为它没有做任何事情:)
省略
@TestExecutionListeners
注释时,Spring会注册3个默认侦听器,包括一个名为DependencyInjectionTestExecutionListener
的侦听器。监听器负责扫描测试类以查找要注入的内容,包括@Resource
注释。此侦听器尝试注入tObj
,但由于未定义范围而失败当您声明
@TestExecutionListeners({})
时,您会抑制DependencyInjectionTestExecutionListener
的注册,因此测试根本不会被tObj
注入,并且因为您的测试没有检查tObj
的存在,所以它通过了修改您的测试,使其执行此操作,否则将失败:
因此,对于空的
@TestExecutionListeners
,测试通过,因为什么都没有发生现在,谈谈你最初的问题。如果您想尝试在测试上下文中注册请求范围,那么请查看
WebApplicationContextUtils.registerWebApplicationScopes()
的源代码,您将找到以下行:你可以试一下,看看你是怎么做的,但可能会有一些奇怪的副作用,因为你并不打算在测试中这样做
相反,我建议重新表述您的测试,这样您就不需要请求作用域bean。这应该不难,如果编写自包含测试,
@Test
的生命周期不应该比请求范围bean的生命周期长。记住,没有必要测试作用域机制,它是Spring的一部分,您可以假设它可以工作# 6 楼答案
这仍然是一个悬而未决的问题:
https://jira.springsource.org/browse/SPR-4588
我通过定义一个自定义上下文加载器(如中所述)实现了这一点
http://forum.springsource.org/showthread.php?p=286280