Tatsuro のテックブログ

アプリ開発の技術情報を発信します。

【Spring Boot × Kotlin】MVC のコントローラクラスを MockMvc でテストする

今回は、MVC のコントローラクラスを MockMvc でテストする方法を解説します。

なお、ここに掲載しているソースコードは以下の環境で動作確認しています。

  • IntelliJ IDEA 2022.2.3 (Community Edition)
  • JDK 17.0.4.1
  • Kotlin 1.6.21
  • Gradle 7.5
  • Spring Boot 2.7.4

プロジェクト作成

プロジェクトを 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")) }
            }
    }

参考

MockMvc と @MockBean で Web レイヤーテスト