はじめに junitでテスト(@Test)する際のspring起動について
junitでテストする際に、DB接続(repository)や外部接続があるクラス(Client)については、
mock化してテストすることが多いと思います。
しかしながら、カバレッジ網羅で検証できるものの、API単体の検証はできないです。
また、API単体の検証を手動でするとなると、その分の工数もかかります。
そのため、Junitを用いて、API単体でのテストができれば、テスト工数の削減できると思い、
junit実行時に、spring起動して、API単体でテストする方法を調べたので記事にします。
※今後どんどんこの記事を育てていきます。
junitでspring起動する方法について
@SpringBootTest を使う
@SpringBootTest をクラスに付与することで、実際のアプリケーション実行時に近い状態で全てのBean(Controller, Service, Repository)をロードします。
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest // 全てのBeanをロードしてコンテキストを起動
@AutoConfigureMockMvc // Controllerを叩くためのMockMvcを自動設定
class MyControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
void testFullFlow() throws Exception {
// Controllerのパスを叩く
// 内部でService -> Repository -> DB と実際に処理が流れる
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk());
}
}
「@AutoConfigureMockMVC」と「mockMvc」とは?
1. @AutoConfigureMockMvc とは?
このアノテーションは、MockMvcインスタンスを自動的に構成し、テストクラスで使えるように準備してくれるものです。
通常、@SpringBootTest だけでは MockMvc は使えませんが、これを追加することで Spring が内部的に「擬似的なサーブレットコンテナ」をセットアップし、DI(@Autowired)できるようになります。
実際の挙動: 本物のサーバー(Tomcatなど)を起動するのではなく、Spring内部でHTTPリクエストをシミュレートします。そのため、高速でありながら、Spring MVCの機能(バリデーション、フィルタ、例外ハンドリングなど)をすべて通してテストできます。
2. mockMvcについて
mockMvc.perform は、**「リクエストを実行する」**ためのメソッドです。引数に「どのようなリクエストを送るか」を指定し、その後に「どのような結果を期待するか」をチェーンメソッドで記述します。
基本的な構文は以下の通りです。
Java
mockMvc.perform(リクエストの設定) // 1. 実行
.andExpect(期待する結果) // 2. 検証
.andDo(追加の操作); // 3. ログ出力など
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
@Test
void testSample() throws Exception {
mockMvc.perform(
get("/api/users/{id}", 1) // GETリクエストを送る
.header("Authorization", "Bearer token") // ヘッダー付与
.param("flag", "true") // クエリパラメータ (?flag=true)
.contentType(MediaType.APPLICATION_JSON) // Content-Type指定
)
.andExpect(status().isOk()) // ステータスコードが200か
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) // JSONが返るか
.andExpect(jsonPath("$.name").value("田中")) // レスポンスのJSONの中身を検証
.andDo(print()); // コンソールにリクエスト/レスポンス詳細を出力
}
リクエスト作成 (MockMvcRequestBuilders)
get("/url"), post("/url"), put("/url"), delete("/url")
.content(jsonString) : POST/PUT時のリクエストボディを設定
.param("key", "value") : クエリパラメータを設定
.header("key", "value") : HTTPヘッダーを設定
結果の検証 (MockMvcResultMatchers)
status().isOk() : 200 OK か
status().isBadRequest() : 400 Bad Request か
view().name("index") : (Thymeleafなどの場合)返却される画面名が正しいか
jsonPath("$.id").value(1) : JSONの特定の項目が期待通りか
デバッグ用 (MockMvcResultHandlers)
print() : テスト実行時のログに、リクエストとレスポンスの詳細(BodyやHeaderなどすべて)を表示します。開発中はこれを入れておくと、エラーの原因がすぐにわかるので非常に便利です。