WebAppConfiguration in Spring Tests

WebAppConfiguration in Frühlingstests

1. Überblick

In diesem Artikel werden wir die Annotation von@WebAppConfigurationim Frühjahr untersuchen, warum wir sie in unseren Integrationstests benötigen und wie wir sie so konfigurieren können, dass diese Tests tatsächlich aWebApplicationContext booten.

2. @WebAppConfiguration

Einfach ausgedrückt handelt es sich um eine Annotation auf Klassenebene, mit der eine Webversion des Anwendungskontexts in Spring Framework erstellt wird.

Es wird verwendet, um anzugeben, dassApplicationContext, das für den Test gebootet wird, eine Instanz vonWebApplicationContext sein sollte.

Ein kurzer Hinweis zur Verwendung - Diese Anmerkung finden wir normalerweise in Integrationstests, daWebApplicationContext zum Erstellen einesMockMvc-Objekts verwendet wird. Weitere Informationen zu Integrationstests mit Springherefinden Sie hier.

3. Laden von aWebApplicationContext

Ab Spring 3.2 wird jetzt das Laden vonWebApplicationContext in Integrationstests unterstützt:

@WebAppConfiguration
@ContextConfiguration(classes = WebConfig.class)
public class EmployeeControllerTest {
    ...
}

Dies weist das Framework vonTestContextan, dass einWebApplicationContext für den Test geladen werden soll.

Und im Hintergrund wird einMockServletContext erstellt und vomTestContext-Framework an dieWebApplicationContext unseres Tests geliefert.

3.1. Einstellmöglichkeiten

Standardmäßig wird der Basisressourcenpfad fürWebApplicationContext auf“file:src/main/webapp”, festgelegt. Dies ist der Standardspeicherort für das Stammverzeichnis der WAR in einem Maven-Projekt.

Wir können dies jedoch überschreiben, indem wir einfach einen alternativen Pfad zur Annotation von@WebAppConfigurationangeben:

@WebAppConfiguration("src/test/webapp")

Anstelle des Dateisystems können wir auch auf einen Basisressourcenpfad aus dem Klassenpfad verweisen:

@WebAppConfiguration("classpath:test-web-resources")

3.2. Caching

SobaldWebApplicationContext geladen ist, wird es zwischengespeichert und für alle nachfolgenden Tests wiederverwendet, die dieselbe eindeutige Kontextkonfiguration innerhalb derselben Testsuite deklarieren.

Weitere Informationen zum Caching finden Sie im AbschnittContext caching des Referenzhandbuchs.

4. Verwenden von@WebAppConfiguration in Tests

Nachdem wir nun verstanden haben, warum wir die Annotation@WebAppConfigurationin unseren Testklassen hinzufügen müssen, sehen wir unswhat happens if we miss adding it an, wenn wirWebApplicationContext verwenden.

@RunWith(SpringJUnit4ClassRunner.class)
// @WebAppConfiguration omitted on purpose
@ContextConfiguration(classes = WebConfig.class)
public class EmployeeTest {

    @Autowired
    private WebApplicationContext webAppContext;
    private MockMvc mockMvc;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();
    }

    ...
}

Beachten Sie, dass wir die Anmerkung auskommentiert haben, um das Szenario zu simulieren, in dem wir vergessen haben, sie hinzuzufügen. Hier ist leicht zu erkennen, warum der Test fehlschlägt, wenn wir den JUnit-Test ausführen:we are trying to autowire the WebApplicationContext in a class where we haven’t set one.

Ein typischeres Beispiel ist jedoch ein Test, der eine webfähige Spring-Konfiguration verwendet. Das ist eigentlich genug, um die Testpause einzulegen.

Werfen wir einen Blick:

@RunWith(SpringJUnit4ClassRunner.class)
// @WebAppConfiguration omitted on purpose
@ContextConfiguration(classes = WebConfig.class)
public class EmployeeTestWithoutMockMvc {

    @Autowired
    private EmployeeController employeeController;

    ...
}

Auch wenn das obige BeispielWebApplicationContext nicht automatisch verdrahtet, schlägt es dennoch fehl, da versucht wird, eine webfähige Konfiguration zu verwenden -WebConfig:

@Configuration
@EnableWebMvc
@ComponentScan("com.example.web")
public class WebConfig implements WebMvcConfigurer {
    ...
}

Die Annotation@EnableWebMvc ist hier der Schuldige - dies erfordert im Grunde einen webfähigen Spring-Kontext, und ohne diesen wird der Test fehlschlagen:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
  No qualifying bean of type [javax.servlet.ServletContext] found for dependency:
    expected at least 1 bean which qualifies as autowire candidate for this dependency.

Dependency annotations:
  {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at o.s.b.f.s.DefaultListableBeanFactory
      .raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
    at o.s.b.f.s.DefaultListableBeanFactory
      .doResolveDependency(DefaultListableBeanFactory.java:1119)
    at o.s.b.f.s.DefaultListableBeanFactory
      .resolveDependency(DefaultListableBeanFactory.java:1014)
    at o.s.b.f.a.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement
      .inject(AutowiredAnnotationBeanPostProcessor.java:545)
    ... 43 more

Das ist also das Problem, das wir leicht beheben können, indem wir unseren Tests die Annotation@WebAppConfigurationhinzufügen.

5. Fazit

In diesem Artikel haben wir gezeigt, wie wir dasTestContext Framework zulassen können, um einWebApplicationContext in unsere Integrationstests zu laden, indem wir einfach die Anmerkung hinzufügen.

Schließlich haben wir uns die Beispiele angesehen, bei denen das Hinzufügen von @ContextConfigurationzum Test nur funktioniert, wenn wir die Annotation von@WebAppConfigurationhinzufügen.

Die Implementierung der Beispiele in diesem Artikel ist in unserem Repository unterGitHub verfügbar.