概要
Spring Framework には End to End の のテストを実現するためにMockMvcという仕組みが存在しています
簡単にいうとAPIをコールしてその結果を評価するという一連の流れをテストすることができます
環境
- Mac OS X 10.10.3
- Eclipse Luna 4.4.1
- Spring Framework 4.1.6
- Spring Tool Suite 3.6.4
- Java 1.8.0_31
- Maven 3.2.1
サンプルプロジェクト作成
過去の記事を参考に作成してください
Spring Framework のバージョンが最新でない場合は pom.xml 「org.springframework-version」のバージョン記載部分を最新のバージョンに変更してください
Spring-Test のライブラリを追加する
pom.xml
にspring-test
のライブラリを追加します
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
junit
を定義するところが既にある場合でもバージョンが4.9未満である場合は4.9以上にしてください
javax.servlet
を読み込んでいますが、デフォルトだと読み込んでいるサーブレットのバージョンが2.5でこれだとCaused by: java.lang.ClassNotFoundException: javax.servlet.SessionCookieConfig
と言われてテストが失敗するので 3.0 系のバージョンを読み込みます
テストコードの作成
src/test/java/test/sample/MockMvcSampleTest.java
にテストコードを作成していきます
STSでプロジェクトを作成するとテスト用のコードは何も作成されないので、適当にテスト用のクラスファイルを作成しましょう
作成したらMockMVC
を使うための定義を記載します
package com.sample;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
@WebAppConfiguration
public class MockMvcSampleTest {
@Autowired
private WebApplicationContext wac;
protected MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void sampleTest() throws Exception {
this.mockMvc.perform(get("/")).andExpect(status().isOk());
}
}
いろいろ書いているので簡単にポイント説明します
クラスの定義の冒頭で3つのアノテーションを宣言しています
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
@WebAppConfiguration
JUnit + MockMvc を使ってテストするために必要な記述です
詳細は正直自分もよくわかっていませんが
RunWith
でランナーを選択してContextConfiguration
でサーブレットの設定が記述されたコンテキストファイルを読み込んでWebAppConfiguration
でWebアプリをテストするための必要なコンテストに触れるようにしています
とにかく1つでも定義がかけるとエラーになるので必ず定義します
次にMockMvc
のオブジェクトを定義する部分です
@Autowired
private WebApplicationContext wac;
protected MockMvc mockMvc;
MockMvc
のオブジェクトを作成するのにWebApplicationContext
が必要で、このオブジェクトは先程のアノテーション+@Autowired
することで勝手に設定されるオブジェクトです
この2つのオブジェクトを使って、サンプルのsetup
メソッドにあるようにbuild
するとMockMvc
のオブジェクトが生成されます
最後にテストの方法です
this.mockMvc.perform(get("/")).andExpect(status().isOk());
ポイントはget
やstatus
というメソッドをimport文でstaticに読み込んでいる部分です
こうすることでテストを書く際にメソッドの呼び出しを直感的に行えます
perform
でコールするAPIのパスとHTTPメソッドを指定して、その結果をandExpect
で評価する感じです
今回のテストの場合はレスポンスコードが20X系であることを確認するテストになっています
Tips
他のHTTPメソッドでコールしたい場合は
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
こんな感じでimportして
this.mockMvc.perform(post("/")).andExpect(status().isMethodNotAllowed());
こんな感じでテストできます
リクエストヘッダを指定したい場合はperform
の後に.header("key", "value")
で指定できます
リクエストパラメータを指定したい場合はperform
の後に.param("key", "value")
で指定できます
(POSTやPUTの場合に)リクエストボディを設定したい場合はperform
の後に.content("body_value")
で指定できます
実行
STSで作成していれば自動的にMavenプロジェクトになっているのでmvn package
などで実行すればライフサイクルの中にテストが含まれるので自動でテストされます
テストだけ個別で実行したい場合はmvn test-compile test
などとすれば実行されます
最後に
Spring Framework にはデフォルトで end to end のテスト方法が含まれているのでAPIサーバを作る場合には割りと簡単にテストが書けそうです
MockMvc を使わないテストも記述することもできるので、メソッド個別でテストしたい場合には別のテストメソッドを作成してテストするといいと思います
JUnit
が使えるのでJUnit
のAssert
等も使うことができます
次回はテスト時に Filter を通してテストする方法を紹介したいと思います
0 件のコメント:
コメントを投稿