我想使用的要求范围内的豆子在我的应用程序。我使用化成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);
    }

与以下豆定义:

 <?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 这似乎是使用弹簧3.0.我用弹簧2.5在这个时候,但是认为它不应该太难打开这个方法使用AbstractJUnit4SpringContextTests 作为该文件建议(确定的文档的链接3.8版本,但我采用的4.4).所以我变的 测试延伸AbstractJUnit4SpringContextTests...相同的消息。相同的问题。和现在的prepareTestInstance()方法我想要的 对复盖没有定义。好吧,也许我会把这些registerScope呼吁别的地方...所以我阅读更多关于 TestExecutionListeners 并认为会更好,因为我不想要继承的弹簧的结构。所以 我改变了我的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/TestScopedBeans-context.xml" })
@TestExecutionListeners({})
public class TestScopedBeans {

期待我会必须创建一个自定义听众,但我的时候我跑了。它的工作!伟大的,但为什么?我看不出其中的任何股票的听众 注册要求的范围或会议的范围,以及他们为什么会?没有什么要说的我想要那个呢,这可能不是一个测试软弹簧的代码...

有帮助吗?

解决方案

,则测试通过,因为它没有做任何事情:)

当省略了@TestExecutionListeners注释,弹簧寄存器3个缺省侦听器,包括一个叫DependencyInjectionTestExecutionListener。这是负责扫描您的测试类找东西注入,包括@Resource注释监听器。此侦听试图注入tObj,和失败,因为未定义范围。

在声明@TestExecutionListeners({}),你抑制DependencyInjectionTestExecutionListener的注册,所以测试永远不会tObj注入可言,因为你的测试不检查tObj的存在,它传递。

修改您的测试,使其做到这一点,它会失败:

@Test
public void testBean() {
    assertNotNull("tObj is null", tObj);
}

所以你的空@TestExecutionListeners,测试通过,因为的没有任何反应的。

现在,在你原来的问题。如果你想尝试注册与测试上下文的请求范围,然后看看对于WebApplicationContextUtils.registerWebApplicationScopes()的源代码,你会发现行:

beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());

您可以试试,看你怎么走,但可能有奇怪的副作用,因为你没有真正的意思做这一个测试。

相反,我会建议换一种方式表述您的测试,让你不要的需要的请求范围豆。这不应该是难事,@Test的生命周期应该是没有任何长于请求范围bean的生命周期,如果你写自包含的测试。请记住,没有必要测试范围机制,它是春天的一部分,你可以假设它的作品。

其他提示

解决方案弹3.2或更新

春天开始3.2版 提供了支持,会议/请求的范围豆一体化试验.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@WebAppConfiguration
public class SampleTest {

    @Autowired WebApplicationContext wac;

    @Autowired MockHttpServletRequest request;

    @Autowired MockHttpSession session;    

    @Autowired MySessionBean mySessionBean;

    @Autowired MyRequestBean myRequestBean;

    @Test
    public void requestScope() throws Exception {
        assertThat(myRequestBean)
           .isSameAs(request.getAttribute("myRequestBean"));
        assertThat(myRequestBean)
           .isSameAs(wac.getBean("myRequestBean", MyRequestBean.class));
    }

    @Test
    public void sessionScope() throws Exception {
        assertThat(mySessionBean)
           .isSameAs(session.getAttribute("mySessionBean"));
        assertThat(mySessionBean)
           .isSameAs(wac.getBean("mySessionBean", MySessionBean.class));
    }
}

详细阅读: 请求和会议范围内的豆


解决方案春天之前3.2监听器

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@TestExecutionListeners({WebContextTestExecutionListener.class,
        DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class})
public class SampleTest {
    ...
}

WebContextTestExecutionListener.java

public  class WebContextTestExecutionListener extends AbstractTestExecutionListener {
    @Override
    public void prepareTestInstance(TestContext testContext) {
        if (testContext.getApplicationContext() instanceof GenericApplicationContext) {
            GenericApplicationContext context = (GenericApplicationContext) testContext.getApplicationContext();
            ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
            beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST,
                    new SimpleThreadScope());
            beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION,
                    new SimpleThreadScope());
        }
    }
}

解决方案春天之前3.2定义范围

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class, locations = "test-config.xml")
public class SampleTest {

...

}

TestConfig.java

@Configuration
@ComponentScan(...)
public class TestConfig {

    @Bean
    public CustomScopeConfigurer customScopeConfigurer(){
        CustomScopeConfigurer scopeConfigurer = new CustomScopeConfigurer();

        HashMap<String, Object> scopes = new HashMap<String, Object>();
        scopes.put(WebApplicationContext.SCOPE_REQUEST,
                new SimpleThreadScope());
        scopes.put(WebApplicationContext.SCOPE_SESSION,
                new SimpleThreadScope());
        scopeConfigurer.setScopes(scopes);

        return scopeConfigurer

}

或xml配置

test-config.xml

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    <property name="scopes">
        <map>
            <entry key="request">
                <bean class="org.springframework.context.support.SimpleThreadScope"/>
            </entry>
        </map>
        <map>
            <entry key="session">
                <bean class="org.springframework.context.support.SimpleThreadScope"/>
            </entry>
        </map>
    </property>
</bean>

源代码

源代码,用于所有提出解决方案:

我已经尝试了多种解决方案,包括@马吕斯的用“WebContextTestExecutionListener”的解决方案,但它并没有为我工作,因为这样的代码创建请求范围之前加载应用程序上下文。

这帮助了我,到底答案是不是新的,但它是很好的: http://tarunsapra.wordpress.com/2011/06 / 28 /的junit - 弹簧 - 会话和请求范围的咖啡豆/

我简单地添加下面的代码片断到我(试验)应用程序上下文:

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    <property name="scopes">
        <map>
            <entry key="request">
                <bean class="org.springframework.context.support.SimpleThreadScope"/>
            </entry>
        </map>
    </property>
</bean>

祝你好运!

一个溶液中,用弹簧4,进行试验时,你需要请求范围的咖啡豆,但不使经由MockMVC任何请求,等等。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(/* ... */)
public class Tests {

    @Autowired
    private GenericApplicationContext context;

    @Before
    public void defineRequestScope() {
        context.getBeanFactory().registerScope(
            WebApplicationContext.SCOPE_REQUEST, new RequestScope());
        RequestContextHolder.setRequestAttributes(
            new ServletRequestAttributes(new MockHttpServletRequest()));
    }

    // ...

这仍然是一个开放的问题:

https://jira.springsource.org/browse/SPR-4588

我能够得到这个定义一个定制的上下文加载工作(大部分)在

概述

http://forum.springsource.org/showthread.php?p=286280

测试请求作用域bean与Spring 解释很以及如何注册并创建和春天有个自定义的范围。

概括地说,如伊科恩解释的,它足以将以下添加到文本上下文配置:

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    <property name="scopes">
        <map>
            <entry key="request">
                <bean class="org.springframework.context.support.SimpleThreadScope"/>
            </entry>
        </map>
    </property>
</bean>

代替使用预定义SimpleThreadScope,基于ThreadLocal的的,它也很容易实现自定义之一,如在文章中解释。

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;

public class CustomScope implements Scope {

    private final Map<String , Object> beanMap = new HashMap<String , Object>();

    public Object get(String name, ObjectFactory<?> factory) {
        Object bean = beanMap.get(name);
        if (null == bean) {
            bean = factory.getObject();
            beanMap.put(name, bean);
        }
        return bean;
    }

    public String getConversationId() {
        // not needed
        return null;
    }

    public void registerDestructionCallback(String arg0, Runnable arg1) {
        // not needed
    }

    public Object remove(String obj) {
        return beanMap.remove(obj);
    }

    public Object resolveContextualObject(String arg0) {
        // not needed
        return null;
    }
}

MariuszS'解决方案的工作,除了我不能得到的交易的直致力于正常。

看来新发布的3.2已经最后作出测试的请求/会议范围内的豆类,第一类的公民。这里的几个博客的更多详细信息。

森Stoyanchev的 弹簧框架3.2RC1:弹簧视测试框架

Sam感动的 弹簧框架3.2RC1:新的功能测试

不阅读该文件有时会驱动器的一个疯狂的。差不多。

如果您使用更短暂的豆子(请求的范围,例),就最有可能也需要改变你的懒惰init默认!否则WebAppContext将无法负荷,并告诉你一些有关失踪请求的范围,这当然是缺失的,因为上下文中仍装载!

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-lazy-init

弹簧们绝对应该把那暗示纳入他们的异常的消息...

如果你不想改变的默认,也有注释的方式:把"@懒惰的(真实的)"后@件等。做单身初始化懒惰和避免的实例,要求范围内的豆子太早。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top