【Spring Boot × Kotlin】MVC のコントローラクラスを MockMvc でテストする
今回は、MVC のコントローラクラスを MockMvc でテストする方法を解説します。
なお、ここに掲載しているソースコードは以下の環境で動作確認しています。
プロジェクト作成
プロジェクトを Spring Initializr にて作成します。各設定項目は以下のように設定します。
- Project: Gradle Project
- Language: Kotlin
- Spring Boot: 2.7.4
- Project Metadata: デフォルト値
- Dependencies: Spring Web, Thymeleaf
モデルの属性値をテストする
以下のようなコントローラクラスをテストします。このクラスは、クエリパラメータから受け取った文字列をモデルの属性に追加するクラスです。
@Controller @RequestMapping("/greeting") class GreetingController { @GetMapping fun greeting( @RequestParam( name = "name", required = false, defaultValue = "world" ) name: String, model: Model ): String { model["name"] = name return "index" } }
上記クラスのテストコードを以下のように書きます。
@WebMvcTest(GreetingController::class) class GreetingControllerTest @Autowired constructor( private val mockMvc: MockMvc ) { @Test fun shouldReturnDefaultValue() { mockMvc.get("/greeting") .andDo { print() }.andExpect { status { isOk() } content { contentType("text/html;charset=UTF-8") } view { name("index") } model { attribute("name", `is`("world")) } } } }
まず、コントローラクラスのテストクラスに @WebMvcTest を付与し、テスト対象のコントロールクラスのクラスリテラルを設定します。そして、テストクラスのコンストラクタで MockMvc のインスタンスをコンストラクタインジェクションで受け取ります。なお、コントローラクラスのコンストラクタインジェクションとは異なり、コンストラクタの @Autowired を省略することはできません。
@WebMvcTest(GreetingController::class) class GreetingControllerTest @Autowired constructor( private val mockMvc: MockMvc ) { ︙ }
次に、テストメソッドを実装します。まず、MockMvc に対して /greeting への GET リクエストを送信させます。
@Test fun shouldReturnDefaultValue() { mockMvc.get("/greeting") ︙ }
なお、MockMvc に HTTP リクエストを送信させる関数は以下の通りです。
関数 | HTTP リクエスト |
---|---|
MockMvc.get | GET |
MockMvc.post | POST |
MockMvc.put | PUT |
MockMvc.patch | PATCH |
MockMvc.delete | DELETE |
MockMvc.options | OPTIONS |
MockMvc.head | HEAD |
次に、MockMvc に実行させるアクションを andDo で設定します。今回はテスト結果を標準出力させるために print を呼び出します。
@Test fun shouldReturnDefaultValue() { mockMvc.get("/greeting") .andDo { print() } ︙ }
そして、GET リクエストを送信させたときの期待値を andExpect で設定します。今回は以下を確認します。
確認項目 | 設定 |
---|---|
ステータスコード | status { isOk() } |
Content-Type | content { contentType("text/html;charset=UTF-8") } |
ビューの名前 | view { name("index") } |
モデルの属性値 | model { attribute("name", is ("world")) } |
@Test fun shouldReturnDefaultValue() { mockMvc.get("/greeting") .andDo { print() }.andExpect { status { isOk() } content { contentType("text/html;charset=UTF-8") } view { name("index") } model { attribute("name", `is`("world")) } } }