web-dev-qa-db-ja.com

Spring Boot JUnitテストで* AutoConfigurationクラスを除外するにはどうすればよいですか?

私は試した:

@RunWith(SpringJUnit4ClassRunner.class)
@EnableAutoConfiguration(exclude=CrshAutoConfiguration.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class LikeControllerTest {

ただし、CRaSSHDはまだ起動します。現在はテストに害はありませんが、ユニットテスト中に不要なモジュールを無効にして、速度を上げ、潜在的な競合を回避したいと思います。

58
Hendy Irawan

一番の答えは、よりシンプルで柔軟性のあるソリューションを指すものではありません。

置くだけ

@TestPropertySource(properties=
{"spring.autoconfigure.exclude=comma.seperated.ClassNames,com.example.FooAutoConfiguration"})
@SpringBootTest
public class MySpringTest {...}

テストクラスの上の注釈。これは、他のテストが現在のテストの特殊なケースの影響を受けないことを意味します。ほとんどのテストに影響する構成がある場合は、現在の上位の回答が示唆するように、代わりにスプリングプロファイルの使用を検討してください。

これをコメントから回答にアップグレードするよう促してくれた@skirschに感謝します。

16
coderatchet

自動構成クラスを除外する別の簡単な方法、

以下に同様の設定をapplication.ymlファイルに追加し、

---
spring:
  profiles: test
  autoconfigure.exclude: org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
47
Kane

Spring Bootで構成されたリポジトリを単独でテストしたいという同様のユースケースがありました(私の場合、Spring Securityの自動構成がなく、テストに失敗しました)。 @SpringApplicationConfigurationSpringApplicationContextLoaderを使用し、JavaDocには

Web以外の機能(リポジトリレイヤーなど)をテストしたり、完全に構成された組み込みサーブレットコンテナを起動したりするために使用できます。

ただし、自分のように、メイン構成エントリポイントを使用して、つまり@SpringApplicationConfiguration(classes = Application.class)のアプローチを使用して、リポジトリレイヤーのみをテストするようにテストを構成する方法を理解できませんでした。

私の解決策は、テスト専用のまったく新しいアプリケーションコンテキストを作成することでした。 src/test/Javaでは、repoというサブパッケージに2つのファイルがあります

  1. RepoIntegrationTest.Java
  2. TestRepoConfig.Java

ここで、RepoIntegrationTest.Java

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestRepoConfig.class)
public class RepoIntegrationTest {

およびTestRepoConfig.Java

@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class TestRepoConfig {

私はトラブルから抜け出しましたが、Spring Bootチームの誰かが代替の推奨ソリューションを提供できれば本当に便利です

28
Matt C

私は同様の問題を抱えていましたが、他の人を助けるかもしれない別の解決策を見つけました。 Spring Profilesを使用して、テスト構成クラスとアプリ構成クラスを分離しました。

  1. 特定のプロファイルでTestConfigクラスを作成し、ここで希望するコンポーネントスキャンからアプリ構成を除外します。

  2. テストクラスで、プロファイルをTestConfigと一致するように設定し、@ ContextConfigurationアノテーションを使用してプロファイルを含めます。

例えば:

設定:

@Profile("test")
@Configuration
@EnableWebMvc
@ComponentScan(
    basePackages="your.base.package",
    excludeFilters = {
            @Filter(type = ASSIGNABLE_TYPE,
                    value = {
                            ExcludedAppConfig1.class,
                            ExcludedAppConfig2.class
            })
    })
public class TestConfig { ...}

テスト:

@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@WebAppConfiguration
public class SomeTest{ ... }
11
Stuart

@EnableAutoConfigurationを使用してApplicationクラスをロードしている場合、テストクラスで@SpringApplicationConfigurationアノテーションを使用しても機能しないと思います。問題は、Applicationクラスに既に@EnableAutoConfiguration注釈があり、CrshAutoConfiguration.Springを除外しないことです。テストクラスの注釈の代わりにその注釈を使用します。 Beanの自動構成を行います。

最善の策は、テストに異なるアプリケーションコンテキストを使用し、そのクラスのCrshAutoConfigurationを除外することだと思います。

いくつかのテストを行いましたが、@EnableAutoConfigurationアノテーションと@SpringApplicationConfigurationを使用している場合、テストクラスのSpringJUnit4ClassRunnerは完全に無視されるようです。

7

新しい @SpringBootTest アノテーションを使用して、 この回答 を取り、@SpringBootApplication構成クラスのプロファイルを使用するように修正しました。 @Profile注釈が必要なのは、他のテスト構成が異なるコンポーネントのスキャンを行うため、これを必要とする特定の統合テスト中にのみこのクラスが取得されるためです。

構成クラスは次のとおりです。

@Profile("specific-profile")
@SpringBootApplication(scanBasePackages={"com.myco.package1", "com.myco.package2"})
public class SpecificTestConfig {

}

次に、テストクラスはこの構成クラスを参照します。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SpecificTestConfig.class })
@ActiveProfiles({"specific-profile"})
public class MyTest {

}
6
James McShane
@SpringBootTest(classes = {Application.class}
              , webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
              , properties="spring.autoconfigure.exclude=com.xx.xx.AutoConfiguration"
               )

参照: https://github.com/spring-projects/spring-boot/issues/8579

4
Kingson wu

同様の問題が発生し、テスト中にメインスプリングブートクラスを除外できませんでした。次のアプローチを使用して解決しました。

@SpringBootApplicationを使用する代わりに、含まれる3つのアノテーションをすべて使用し、@ Configurationに名前を割り当てます。

@Configuration("myApp")
@EnableAutoConfiguration
@ComponentScan
public class MyApp { .. }

テストクラスで、まったく同じ名前で構成を定義します。

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
// ugly hack how to exclude main configuration
@Configuration("myApp")
@SpringApplicationConfiguration(classes = MyTest.class)
public class MyTest { ... }

これが役立つはずです。構成注釈の自動スキャンを無効にする方法をいくつか用意しておくといいでしょう...

2
myroch

持ち込むSpringBootApplication/Configurationがテスト構成が含まれるパッケージをコンポーネントスキャンしているという問題である場合は、実際にテスト構成から@Configurationアノテーションを削除し、@ SpringBootTestアノテーションでそれらを引き続き使用できます。たとえば、メイン構成であるクラスApplicationと、すべてのテストではなく特定のテストの構成であるクラスTestConfigurationがある場合、次のようにクラスを設定できます。

@Import(Application.class) //or the specific configurations you want
//(Optional) Other Annotations that will not trigger an autowire
public class TestConfiguration {
    //your custom test configuration
}

そして、次の2つの方法のいずれかでテストを構成できます。

  1. 通常の構成の場合:

    @SpringBootTest(classes = {Application.class}) //won't component scan your configuration because it doesn't have an autowire-able annotation
    //Other annotations here
    public class TestThatUsesNormalApplication {
        //my test code
    }
    
  2. テストカスタムテスト構成の場合:

    @SpringBootTest(classes = {TestConfiguration.class}) //this still works!
    //Other annotations here
    public class TestThatUsesCustomTestConfiguration {
        //my test code
    }
    
2
Taugenichts

私はある日、同様の問題に苦しんでいます...私のシナリオ:

SpringBootアプリケーションがあり、scr/main/resourcesapplicationContext.xmlを使用して、すべてのSpring Beanを構成します。テスト(統合テスト)には、test/resourcesで別のapplicationContext.xmlを使用し、期待どおりに動作しました:Spring/SpringBootがオーバーライドしますapplicationContext.xmlscr/main/resourcesから、テスト用に設定されたBeanを含むテスト用のものを使用します。

ただし、1つのUnitTestについてのみ、テストで使用されるapplicationContext.xmlのカスタマイズがさらに必要でした。このテストについては、モッキートBeanを使用したかっただけです。 mockverifyができたので、ここで1日の頭痛が始まりました。

問題は、Spring/SpringBootがscr/main/resourcesからのファイルが同じ名前を持っている場合のみ、test/resourcesからのapplicationContext.xmlをオーバーライドしないことです。私は何時間も使ってみました:

@RunWith(SpringJUnit4ClassRunner.class)
@OverrideAutoConfiguration(enabled=true)
@ContextConfiguration({"classpath:applicationContext-test.xml"})

動作しませんでした。Springは最初にscr/main/resourcesapplicationContext.xmlからBeanをロードしていました

@myrochと@Stuartの回答に基づく私のソリューション:

  1. アプリケーションのメイン構成を定義します。

    @Configuration @ImportResource({"classpath:applicationContext.xml"}) public class MainAppConfig { }

これはアプリケーションで使用されます

@SpringBootApplication
@Import(MainAppConfig.class)
public class SuppressionMain implements CommandLineRunner
  1. メイン構成を除外するテストのTestConfigurationを定義します

    @ComponentScan(basePackages = "com.mypackage"、excludeFilters = {@ ComponentScan.Filter(type = ASSIGNABLE_TYPE、value = {MainAppConfig.class})})@EnableAutoConfiguration public class TestConfig {}

これにより、このテストでは、SpringはapplicationContext.xmlをロードせず、このテストに固有のカスタム構成のみをロードします。

1
razvang

現在、SpringBoot 2.0の最良の解決策はプロファイルを使用することだと思います

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
@ActiveProfiles("test")
public class ExcludeAutoConfigIntegrationTest {
    // ...
} 

spring.autoconfigure.exclude = org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

とにかく以下で link これを解決するために6つの異なる選択肢を与えます。

0
oriaj

Spring Boot 1.4.x以降でこの問題が発生している場合、@OverrideAutoConfiguration(enabled=true)を使用して問題を解決できる場合があります。

ここで質問/回答されたものと同様 https://stackoverflow.com/a/39253304/1410035

0
Tom Saleeba

私もこれに苦労し、 @ ComponentScan ドキュメントの大まかな読み取りの後にテストコンテキストを分離する簡単なパターンを見つけました。

/ **
*パッケージを指定するための{@link #basePackages}のタイプセーフな代替
*注釈付きコンポーネントをスキャンします。指定された各クラスのパッケージがスキャンされます。
*各パッケージに特別なノーオペレーションマーカークラスまたはインターフェイスを作成することを検討してください
*この属性によって参照される以外の目的はありません。
* /
Class<?>[] basePackageClasses() default {};

  1. スプリングテスト用のパッケージ("com.example.test")を作成します。
  2. パッケージ内にコンテキスト修飾子としてマーカーインターフェイスを作成します。
  3. BasePackageClassesのパラメーターとしてマーカーインターフェイス参照を提供します。


IsolatedTest.Java

package com.example.test;

@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan(basePackageClasses = {TestDomain.class})
@SpringApplicationConfiguration(classes = IsolatedTest.Config.class)
public class IsolatedTest {

     String expected = "Read the documentation on @ComponentScan";
     String actual = "Too lazy when I can just search on Stack Overflow.";

      @Test
      public void testSomething() throws Exception {
          assertEquals(expected, actual);
      }

      @ComponentScan(basePackageClasses = {TestDomain.class})
      public static class Config {
      public static void main(String[] args) {
          SpringApplication.run(Config.class, args);
      }
    }
}

...

TestDomain.Java

package com.example.test;

public interface TestDomain {
//noop marker
}
0
Eddie B