web-dev-qa-db-ja.com

テストメソッド内のSpringアプリケーションコンテキストを再読み込みまたは更新しますか?

ProfileResolverを使用しているため、テストクラスの1つのメソッド内のapplicationContextでアクティブなSpringプロファイルを変更する必要があります。変更するには、コンテストを更新する前に1行のコードを実行する必要があります。私は以下を試しました:

@WebAppConfiguration
@ContextConfiguration(locations = {"/web/WEB-INF/spring.xml"})
@ActiveProfiles(resolver = BaseActiveProfilesResolverTest.class)
public class ControllerTest extends AbstractTestNGSpringContextTests {
    @Test
    public void test() throws Exception {
        codeToSetActiveProfiles(...);
        ((ConfigurableApplicationContext)this.applicationContext).refresh();
        ... tests here ...
        codeToSetActiveProfiles(... back to prior profiles ...);
        ... ideally refresh/reload the context for future tests
    }
}

しかし、私は得ます:

Java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once

DirtiesContextは、クラス/メソッドの実行前ではなく実行後に実行されるため機能しません。更新/再ロードを実行する前にコード行を実行する必要があります。

助言がありますか?実行中のリスナー/フックを調べてみましたが、この動作を実現するために自分自身を挿入する明確な場所が見つかりませんでした。

13
David E

設計上、ApplicationContextのプログラムによる更新は、Spring TestContext Frameworkでは明示的にサポートされていません。さらに、テストメソッドがコンテキストを更新することは意図されていません。

したがって、リフレッシュの必要性を再評価し、別のアクティブプロファイルのセットを必要とするテストメソッドを専用のテストクラスに配置するなどの代替案を検討することをお勧めします。

要約すると、@ActiveProfilesdeclarative構成(valueおよびprofiles属性を介して)およびprogrammaticテスト用のアクティブプロファイルの構成(resolver属性を介して)。ただし、メソッドレベルではなくテストクラスレベルでのみ。別のオプションは、ApplicationContextInitializerを実装し、@ContextConfiguration(initializers=...)を介して構成することです。

ApplicationContextbeforeに影響を与える他の唯一の方法は、SmartContextLoaderを実装するか、提供されたクラスの1つを拡張して@ContextConfiguration(loader=...)。たとえば、AbstractGenericContextLoader.customizeContext()を使用すると、ローダーによって作成されたGenericApplicationContextをカスタマイズできますBean定義がロードされますコンテキストですが、beforeコンテキストが更新されます。 "

宜しくお願いします、

Sam(Spring TestContext Frameworkの作者)

15
Sam Brannen

コンテキストの更新をトリガーする素敵な小さなハックがあります-org.springframework.cloud.context.refresh.ContextRefresherを使用することです。

この方法が適しているかどうかは100%わかりません。必須spring-cloud-context依存関係。ただし、これはtest依存関係として追加され、本番クラスパスにリークしない場合があります。

このリフレッシャーを使用するには、org.springframework.cloud.autoconfigure.RefreshAutoConfiguration構成もインポートする必要があります。これにより、RefreshScopeスコープがapplicationContextに追加され、実際に内部でジョブが実行されます。

したがって、次のようにテストを変更します。

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.context.refresh.ContextRefresher;    
// your other imports


@WebAppConfiguration
@ContextConfiguration(locations = {"/web/WEB-INF/spring.xml"}, classes = RefreshAutoConfiguration.class)
@ActiveProfiles(resolver = BaseActiveProfilesResolverTest.class)
public class ControllerTest extends AbstractTestNGSpringContextTests {

    @Autowired
    private ContextRefresher contextRefresher;

    @Test
    public void test() throws Exception {
        // doSmth before
        contextRefresher.refresh();
        // context is refreshed - continue testing
    }

}
1
Ivan Pronin

すべてのアプリケーションコンテキストが複数のrefreshをサポートするわけではありません。 AbstractRefreshableApplicationContextのjavadocによると、そのサブクラスまたはAbstractRefreshableWebApplicationContextのサブクラスのみがrefreshを2回以上受け入れます...およびGenericApplicationContextはそれらの1つではありません。

ホットリフレッシュをサポートするには、ApplicationContextに別のクラスを使用する必要があります。

編集:

@ContextConfigurationアノテーションを使用しているので、カスタムのContextLoaderまたはSmartContextLoader実装を使用して、Springがより愚かでないApplicationContextを使用するように強制する必要があります。しかし、そのためのクリーンできちんとした方法を見つけることはできませんでした。したがって、テストクラスでXmlWebApplicationContextが必要な場合は、@ContextConfigurationを使用せず、手作業でコンテキストを作成して更新します@Beforeメソッド内またはテストの開始時。

これは実際にはあなたの質問に答えるものではありませんが、回避策として見ることができます。

0
Serge Ballesta