SpringテストでのWebAppConfiguration

SpringテストのWebAppConfiguration

1. 概要

この記事では、Springの@WebAppConfigurationアノテーション、統合テストで必要な理由、およびこれらのテストが実際にWebApplicationContextをブートストラップするように構成する方法について説明します。

2. @WebAppConfiguration

簡単に言えば、これはSpring FrameworkでアプリケーションコンテキストのWebバージョンを作成するために使用されるクラスレベルのアノテーションです。

これは、テスト用にブートストラップされるApplicationContextWebApplicationContextのインスタンスであることを示すために使用されます。

使用法についての簡単なメモ–WebApplicationContextMockMvcオブジェクトの構築に使用されるため、通常、統合テストでこのアノテーションが見つかります。 Springhereとの統合テストに関する詳細情報を見つけることができます。

3. WebApplicationContextのロード

Spring 3.2以降、統合テストでWebApplicationContextをロードできるようになりました。

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

これは、WebApplicationContextをテスト用にロードする必要があることをTestContextフレームワークに指示します。

また、バックグラウンドでMockServletContextが作成され、TestContextフレームワークによってテストのWebApplicationContextに提供されます。

3.1. 構成オプション

デフォルトでは、WebApplicationContextのベースリソースパスは“file:src/main/webapp”,に設定されます。これは、MavenプロジェクトのWARのルートのデフォルトの場所です。

ただし、@WebAppConfigurationアノテーションへの代替パスを提供するだけで、これをオーバーライドできます。

@WebAppConfiguration("src/test/webapp")

ファイルシステムではなく、クラスパスからベースリソースパスを参照することもできます。

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

3.2. キャッシング

WebApplicationContextがロードされると、キャッシュされ、同じテストスイート内で同じ一意のコンテキスト構成を宣言する後続のすべてのテストで再利用されます。

キャッシュの詳細については、リファレンスマニュアルのContext cachingセクションを参照してください。

4. テストでの@WebAppConfigurationの使用

テストクラスに@WebAppConfigurationアノテーションを追加する必要がある理由がわかったので、WebApplicationContextを使用しているときにwhat happens if we miss adding itを見てみましょう。

@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();
    }

    ...
}

追加するのを忘れたシナリオをシミュレートするために注釈をコメント化したことに注意してください。 ここで、JUnitテストを実行したときにテストが失敗する理由を簡単に確認できます。we are trying to autowire the WebApplicationContext in a class where we haven’t set one.

ただし、より一般的な例は、Web対応のSpring構成を使用するテストです。実際には、テストを中断するのに十分です。

みてみましょう:

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

    @Autowired
    private EmployeeController employeeController;

    ...
}

上記の例ではWebApplicationContextを自動配線していませんが、Web対応の構成を使用しようとしているため失敗します–WebConfig

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

注釈@EnableWebMvcがここでの原因です。これには、基本的にWeb対応のSpringコンテキストが必要ですが、それがないと、テストが失敗することがわかります。

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

これが、テストに@WebAppConfigurationアノテーションを追加することで簡単に修正できる問題です。

5. 結論

この記事では、アノテーションを追加するだけで、TestContextフレームワークにWebApplicationContextを統合テストにロードさせる方法を示しました。

最後に、@ContextConfigurationをテストに追加しても、@WebAppConfigurationアノテーションを追加しないとこれが機能しないという例を確認しました。

この記事の例の実装は、GitHubのリポジトリで入手できます。