web-dev-qa-db-ja.com

さまざまなテスト方法にさまざまなSpringテストコンテキスト構成を使用する

内部テストコンテキスト構成クラスを利用するSpringベースのJUnitテストクラスがあります

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ServiceTest.Config.class)
public class ServiceTest {

    @Test
    public void someTest() {
    ...

    @Configuration
    @PropertySource(value = { "classpath:application.properties" })
    @ComponentScan({ "..." })
    public static class Config {
    ...

最近、新しい機能がServiceクラスに導入されました。この機能については、関連するテストをServiceTestに追加する必要があります。ただし、これらには別のテストコンテキスト構成クラスを作成する必要もあります(既存のConfigクラスの内部はかなり複雑であり、古いテストと新しいテストの両方を提供するように変更することは、可能であれば非常に難しいようです)

1つのテストクラスの特定のテストメソッドが1つの構成クラスを使用し、他のメソッドが別の構成クラスを使用するようにする方法はありますか? @ContextConfigurationはクラスレベルでのみ適用できるように思われるため、解決策は、独自のコンテキスト構成クラスを利用する新しいテスト用に別のテストクラスを作成することです。ただし、同じサービスクラスが2つの異なるテストクラスでカバーされていることを意味します

12
hammerfest

これを解決する必要がある場合は、次のアプローチを使用します。

  • アノテーションを使用する代わりに、セットアップメソッドでコンテキストを手動で構築します。
  • 共通のテストコードを基本クラスに移動して拡張します。これにより、さまざまな春のコンテキストでテストを実行できます。
  • 上記の2つの組み合わせ。基本クラスには、フラグメントからSpringコンテキストを構築するメソッドが含まれています(拡張機能はこれをオーバーライドできます)。これにより、意味をなさないテストケースをオーバーライドしたり、一部のテストで余分な前後の作業を行ったりすることもできます。

アノテーションは一般的なケースのみを解決することに注意してください。共通点を離れるときは、彼らの仕事の一部またはすべてを複製する必要があります。

3
Aaron Digulla

コンテキストを手動で構築するというAaronの提案では、良い例が見つからなかったので、それを機能させるために時間を費やした後、他の誰かに役立つ場合に備えて、使用したコードの簡単なバージョンを投稿すると思いました。

class MyTest {

    @Autowired
    private SomeService service;
    @Autowired
    private ConfigurableApplicationContext applicationContext;

    public void init(Class<?> testClass) throws Exception {
        TestContextManager testContextManager = new TestContextManager(testClass);
        testContextManager.prepareTestInstance(this);
    }

    @After
    public void tearDown() throws Exception {
        applicationContext.close();
    }

    @Test
    public void test1() throws Exception {
        init(ConfigATest.class);
        service.doSomething();
        // assert something
    }

    @Test
    public void test2() throws Exception {
        init(ConfigBTest.class);
        service.doSomething();
        // assert something
    }

    @ContextConfiguration(classes = {
        ConfigATest.ConfigA.class
    })
    static class ConfigATest {
        static class ConfigA {
            @Bean
            public SomeService someService() {
                return new SomeService(new A());
            }
        }
    }

    @ContextConfiguration(classes = {
        ConfigBTest.ConfigB.class
    })
    static class ConfigBTest {
        static class ConfigB {
            @Bean
            public SomeService someService() {
                return new SomeService(new B());
            }
        }

    }
}
12
Andy