31

アプリでリクエスト スコープ 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

しかし、Spring 3.0 で廃止されたように見えるAbstractDependencyInjectionSpringContextTestsを使用していることに気付きました。現時点ではSpring 2.5を使用していますが、ドキュメントが示唆するように、このメソッドをAbstractJUnit4SpringContextTestsを使用するように切り替えるのはそれほど難しくないと考えました(ドキュメントは3.8バージョンにリンクしていますが、私は4.4を使用しています)。したがって、テストを変更して AbstractJUnit4SpringContextTests を拡張します...同じメッセージ。同じ問題。そして、オーバーライドしたい prepareTestInstance() メソッドが定義されていません。OK、多分私はそれらの registerScope 呼び出しを別の場所に置きます...だから私はTestExecutionListenersについてもっと読んで、Springパッケージ構造を継承する必要がないので、それがより良いと思います。そこで、テストを次のように変更しました。

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

カスタムリスナーを作成する必要があると思っていましたが、それを実行したときです。できます!素晴らしいですが、なぜですか?ストックリスナーがリクエストスコープまたはセッションスコープを登録している場所がわかりません。なぜですか? まだ何も言いたいことはありません。これはSpring MVCコードのテストではないかもしれません...

4

8 に答える 8

56

Spring 3.2 以降のソリューション

バージョン 3.2 以降の Springは、統合テスト用のセッション/リクエスト スコープ Bean のサポートを提供します

@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));
    }
}

続きを読む:リクエストおよびセッション スコープ Bean


リスナーを使用した 3.2 より前の Spring のソリューション

@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 より前の Spring のソリューション

@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>

ソースコード

提示されたすべてのソリューションのソース コード:

于 2011-01-11T19:59:47.450 に答える
9

「WebContextTestExecutionListener」を使用した@Mariusのソリューションを含むいくつかのソリューションを試しましたが、このコードがリクエストスコープを作成する前にアプリケーションコンテキストを読み込んだため、うまくいきませんでした。

最終的に私を助けた答えは新しいものではありませんが、それは良いことです:http: //tarunsapra.wordpress.com/2011/06/28/junit-spring-session-and-request-scope-beans/

次のスニペットを(テスト)アプリケーションコンテキストに追加しただけです。

<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>

幸運を!

于 2013-03-19T15:42:48.133 に答える
8

リクエスト スコープの Bean が必要であるがMockMVC、などを介してリクエストを行っていない場合に備えて、Spring 4 でテストされたソリューション。

@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()));
    }

    // ...
于 2016-06-08T10:05:49.123 に答える
2

これは未解決の問題です。

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

で概説されているようにカスタムコンテキストローダーを定義することで、これを(ほとんど)機能させることができました

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

于 2011-02-10T19:06:28.427 に答える
1

MariuszSのソリューションは機能しますが、トランザクションを適切にコミットできませんでした。

新しくリリースされた3.2は、最終的にテスト要求/セッションスコープのBeanを第一級市民にしたようです。詳細については、いくつかのブログをご覧ください。

RossenStoyanchevのSpringFramework3.2 RC1:SpringMVCテストフレームワーク

SamBrannenのSpringFramework3.2 RC1:新しいテスト機能

于 2012-12-20T03:50:33.370 に答える
0

ドキュメントを読まないと気が狂ってしまうことがあります。ほとんど。

有効期間の短い Bean (リクエスト スコープなど) を使用している場合は、おそらく遅延初期化のデフォルトも変更する必要があります。そうしないと、WebAppContext の読み込みに失敗し、コンテキストがまだ読み込まれているため、リクエスト スコープが欠落していることがわかります。これはもちろん欠落しています。

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

Spring の連中は、間違いなくそのヒントを例外メッセージに入れる必要があります...

デフォルトを変更したくない場合は、アノテーションの方法もあります。 @Component などの後に "@Lazy(true)" を配置して、シングルトンを遅延初期化し、リクエスト スコープの Bean のインスタンス化が早すぎるのを回避します。

于 2012-08-08T10:04:05.823 に答える