it-swarm.com.de

So schließen Sie * AutoConfiguration-Klassen in Spring Boot-JUnit-Tests aus?

Ich habe es versucht:

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

Der CRaSSHD läuft jedoch immer noch hoch. Während es dem Test momentan nicht schadet, möchte ich während des Komponententests unnötige Module deaktivieren, um die Geschwindigkeit zu erhöhen und mögliche Konflikte zu vermeiden.

50
Hendy Irawan

Top-Antworten deuten nicht auf eine noch einfachere und flexiblere Lösung hin.

stell einfach ein 

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

anmerkung über Ihrer Testklasse. Dies bedeutet, dass andere Tests nicht vom Sonderfall des aktuellen Tests betroffen sind. Wenn die meisten Ihrer Tests von einer Konfiguration betroffen sind, sollten Sie stattdessen das Federprofil verwenden, da die aktuelle Top-Antwort nahelegt.

Danke an @skirsch, dass Sie mich dazu ermutigt haben, dies von einem Kommentar zu einer Antwort zu verbessern.

3
coderatchet

Eine weitere einfache Möglichkeit, die automatischen Konfigurationsklassen auszuschließen,

Fügen Sie eine ähnliche Konfiguration zu Ihrer application.yml -Datei hinzu.

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

Ich hatte einen ähnlichen Anwendungsfall, bei dem ich ein Spring Boot-konfiguriertes Repository isoliert testen wollte (in meinem Fall ohne Spring Security-Autokonfiguration, die meinen Test nicht bestanden hat). @SpringApplicationConfiguration verwendet SpringApplicationContextLoader und das hat eine JavaDoc-Angabe

Kann verwendet werden, um Nicht-Web-Features (wie eine Repository-Schicht) oder .__ zu testen. Starten Sie einen vollständig konfigurierten eingebetteten Servlet-Container.

Wie Sie selbst konnte ich jedoch nicht herausfinden, wie Sie den Test so konfigurieren sollen, dass nur der Repository-Layer mit dem Hauptkonfigurationseintrag getestet wird, d. H. Mit Ihrem Ansatz von @SpringApplicationConfiguration(classes = Application.class).

Meine Lösung bestand darin, einen völlig neuen Anwendungskontext zu erstellen, der ausschließlich zum Testen dient. In src/test/Java habe ich also zwei Dateien in einem Unterpaket namens Repo

  1. RepoIntegrationTest.Java
  2. TestRepoConfig.Java

wo RepoIntegrationTest.Java hat

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

und TestRepoConfig.Java hat

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

Es hat mich aus den Schwierigkeiten gerissen, aber es wäre wirklich nützlich, wenn jemand aus dem Spring Boot-Team eine alternative empfohlene Lösung anbieten könnte

27
Matt C

Ich hatte ein ähnliches Problem, kam aber zu einer anderen Lösung, die anderen helfen könnte. Ich habe Spring Profiles verwendet, um Test- und App-Konfigurationsklassen zu trennen. 

  1. Erstellen Sie eine TestConfig-Klasse mit einem bestimmten Profil, und schließen Sie jegliche App-Konfiguration von der hier untersuchten Komponentensuche aus.

  2. Legen Sie in Ihrer Testklasse fest, dass das Profil mit der TestConfig übereinstimmt, und fügen Sie es mithilfe der Annotation @ContextConfiguration ein.

Zum Beispiel:

aufbau:

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

prüfung:

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

Ich denke, dass die Verwendung der Annotation @EnableAutoConfiguration für eine Testklasse nicht funktioniert, wenn Sie @SpringApplicationConfiguration verwenden, um Ihre Application Klasse zu laden. Die Sache ist, dass Sie bereits eine @EnableAutoConfiguration-Annotation in der Application -Klasse haben, die die CrshAutoConfiguration.Spring -Kennung nicht ausschließt. Diese VARIABLE-- verwendet diese Annotation anstelle der in Ihrer Testklasse für die automatische Konfiguration von deinen Bohnen. 

Ich denke, dass Sie am besten einen anderen Anwendungskontext für Ihre Tests verwenden und CrshAutoConfiguration in dieser Klasse ausschließen.

Ich habe einige Tests durchgeführt und es scheint, dass @EnableAutoConfiguration in der Testklasse vollständig ignoriert wird, wenn Sie die Annotation @SpringApplicationConfiguration und SpringJUnit4ClassRunner verwenden.

6

Mit der neuen Annotation @SpringBootTest nahm ich diese Antwort und modifizierte sie, um Profile mit einer @SpringBootApplication-Konfigurationsklasse zu verwenden. Die @Profile-Annotation ist erforderlich, damit diese Klasse nur während der spezifischen Integrationstests abgerufen wird, die dies benötigen, da andere Testkonfigurationen andere Komponenten scannen.

Hier ist die Konfigurationsklasse:

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

}

Dann verweist die Testklasse auf diese Konfigurationsklasse:

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

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

4
Kingson wu

kam in die gleiche Art von Problem, konnte die Hauptklasse der Federstiefel während des Tests nicht ausschließen. Gelöst mit dem folgenden Ansatz.

Verwenden Sie anstelle von @SpringBootApplication alle drei darin enthaltenen Annotationen, und weisen Sie @Configuration den Namen zu

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

Definieren Sie in Ihrer Testklasse eine Konfiguration mit genau demselben Namen:

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

Das sollte helfen. Es wäre schön, einen besseren Weg zu finden, wie Sie das automatische Scannen für Konfigurationsanmerkungen deaktivieren können ...

2
myroch

Ich denke, dass die derzeit beste Lösung für springBoot 2.0 die Verwendung von Profilen ist

@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

trotzdem im folgenden Link 6 verschiedene Alternativen geben, um dies zu lösen.

1
oriaj

Wenn das Problem darin besteht, dass Ihre SpringBootApplication/-Konfiguration, die Sie mitbringen, eine Komponente ist, die das Paket überprüft, in dem Ihre Testkonfigurationen enthalten sind, können Sie die Annotation @Configuration aus den Testkonfigurationen entfernen und sie in den Annotationen @SpringBootTest verwenden. Wenn Sie beispielsweise eine Klasse Application haben, die Ihre Hauptkonfiguration ist, und eine Klasse TestConfiguration, die zwar eine bestimmte Konfiguration ist, aber nicht alle Tests, können Sie Ihre Klassen wie folgt einrichten:

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

Dann können Sie Ihre Tests auf zwei Arten konfigurieren:

  1. Mit der regulären Konfiguration:

    @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. Mit der Test-Testkonfiguration:

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

Wenn Sie dieses Problem mit Spring Boot 1.4.x oder höher haben, können Sie möglicherweise @OverrideAutoConfiguration(enabled=true) verwenden, um das Problem zu lösen.

Ähnlich wie hier gefragt/beantwortet wurde https://stackoverflow.com/a/39253304/1410035

0
Tom Saleeba

Ich kämpfte auch damit und fand ein einfaches Muster, um den Testkontext nach einem flüchtigen Lesen der @ ComponentScan -Dokumente zu isolieren.

/ **
* Typensichere Alternative zu {@link #basePackages} zur Angabe der Pakete
*, um nach mit Anmerkungen versehenen Komponenten zu suchen. Das Paket jeder angegebenen Klasse wird gescannt.
* Erwägen Sie, in jedem Paket eine spezielle No-Op-Markierungsklasse oder -Schnittstelle zu erstellen
* das hat keinen anderen Zweck, als von diesem Attribut referenziert zu werden.
* /
Class<?>[] basePackageClasses() default {};

  1. Erstellen Sie ein Paket für Ihre Frühlingstests, ("com.example.test").
  2. Erstellen Sie eine Markierungsschnittstelle im Paket als Kontextqualifizierer.
  3. Stellen Sie die Markierungsschnittstellenreferenz als Parameter für basePackageClasses bereit.

Beispiel


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

Ich habe einen Tag lang mit einem ähnlichen Problem gekämpft ... Mein Szenario:

Ich habe eine SpringBoot-Anwendung und verwende applicationContext.xml in scr/main/resources, um alle meine Spring Beans zu konfigurieren. Zum Testen (Integrationstest) verwende ich ein anderes applicationContext.xml in test/resources und die Dinge funktionierten wie erwartet: Spring/SpringBoot würde applicationContext.xml von scr/main/resources überschreiben und das für Testing verwenden welche die zum Testen konfigurierten Beans enthielten.

Nur für einen UnitTest wollte ich noch eine weitere Anpassung für die in Testing verwendete applicationContext.xml , nur für diesen Test wollte ich ein paar Mockito-Beans verwenden, damit ich mock und verify verwenden konnte, und hier begann mein eintägiger Kopf -schmerzen!

Das Problem ist, dass Spring/SpringBoot die applicationContext.xml von scr/main/resources NUR nicht überschreibt, WENN die Datei von test/resources den gleichen Namen hat . Ich habe stundenlang versucht, etwas zu verwenden:

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

es funktionierte nicht, Spring lud zuerst die Beans aus applicationContext.xml in scr/main/resources

Meine Lösung basiert auf den Antworten von @myroch und @Stuart:

  1. Definieren Sie die Hauptkonfiguration der Anwendung:

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

dies wird in der Anwendung verwendet

@SpringBootApplication
@Import(MainAppConfig.class)
public class SuppressionMain implements CommandLineRunner
  1. Definieren Sie eine TestConfiguration für den Test, bei der Sie die Hauptkonfiguration ausschließen möchten

    @ComponentScan ( BasePackages = "com.mypackage", ExcludeFilters = { @ ComponentScan.Filter (type = ASSIGNABLE_TYPE, Value = {MainAppConfig.class}) ) .__). @ EnableAutoConfiguration Public Klasse TestConfig {}

Auf diese Weise lädt Spring für diesen Test applicationContext.xml nicht und nur die benutzerdefinierte Konfiguration, die für diesen Test spezifisch ist.

0
razvang