JUnit

MockMvcを利用してコントローラクラスのテストを行ってみた

MockMvcとは、アプリケーションサーバ上にデプロイすることなくSpring MVCの動作を再現できるフレームワークで、コントローラクラスのテストを行う際に利用することができる。

今回は、MockMvcを利用したコントローラクラスのテストクラスを作成してみたので、共有する。

なお、MockMvcについての詳細は、以下のサイトを参照のこと。
https://terasolunaorg.github.io/guideline/5.4.1.RELEASE/ja/UnitTest/ImplementsOfUnitTest/UsageOfLibraryForTest.html#usageoflibraryfortestmockmvcoverview

前提条件

下記記事の実装が完了していること。

ユーティリティクラスの良い例と悪い例を実装してみたごく単純なJavaクラスの実装であっても、実装方法はいくつか考えられるため、その中で「最も良い」実装方法を検討し選択する必要がある。今回...

サンプルプログラムの作成

作成したサンプルプログラムの構成は以下の通り。
サンプルプログラムの構成
なお、上記の赤枠は、前提条件のプログラムから変更したプログラムである。

今回のテスト対象となるコントローラクラスの内容は以下の通り。

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Controller
public class DemoController {

    /**
     * ハッシュマップをセッションに追加し、初期表示画面に遷移
     * @param request HttpServletRequestオブジェクト
     * @return 初期表示画面へのパス
     */
    @GetMapping("/")
    public String index(HttpServletRequest request){
        // セッションを生成
        HttpSession session = request.getSession(true);

        // ハッシュマップを生成し、セッションに追加
        HashMap<String, List<String>> hashMap = createHashMap();
        session.setAttribute("sesHashMap", hashMap);

        return "index";
    }

    /**
     * セッションから指定したキー値に対応するリストを取得し、次画面に遷移
     * @param model Modelオブジェクト
     * @param request HttpServletRequestオブジェクト
     * @return 次画面へのパス
     */
    @PostMapping("/next")
    public String next(Model model, HttpServletRequest request){
        // セッションから指定したキー値に対応するリストを取得し、sessionListに設定
        List<String> hashList = DemoUtil.getHashList("key1");
        model.addAttribute("sessionList", hashList);

        // セッションの値を破棄し、次画面に遷移
        request.getSession(false).invalidate();
        return "next";
    }

    /**
     * セッションに設定するハッシュマップを生成する
     * @return 生成したハッシュマップ
     */
    private HashMap<String, List<String>> createHashMap(){
        HashMap<String, List<String>> hashMap = new HashMap<>();

        List<String> hashList1 = new ArrayList<>();
        hashList1.add("item1");
        hashList1.add("item2");
        hashList1.add("item3");
        hashMap.put("key1", hashList1);

        List<String> hashList2 = new ArrayList<>();
        hashList2.add("item4");
        hashList2.add("item5");
        hashMap.put("key2", hashList2);

        return hashMap;
    }
}



今回のテストクラスの内容は以下の通りで、MockMvcを利用して、コントローラクラスの各メソッドの動作を検証する内容になっている。

package com.example.demo;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.servlet.http.HttpSession;

import static org.junit.Assert.assertNull;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class DemoControllerTest {

    /**
     * MockMvcオブジェクト
     */
    private MockMvc mockMvc;

    /**
     * テスト対象クラス
     */
    @Autowired
    DemoController target;

    /**
     * 前処理(各テストケースを実行する前に行われる処理)
     */
    @Before
    public void setup() {
        // MockMvcオブジェクトにテスト対象メソッドを設定
        mockMvc = MockMvcBuilders.standaloneSetup(target).build();
    }

    /**
     * DemoControllerクラスのindexメソッドを確認するためのテスト
     */
    @Test
    public void indexTest() throws Exception{
       // テスト対象メソッド(index)を実行
        mockMvc.perform(get("/"))
                    // HTTPステータスがOKであることを確認
                .andExpect(status().isOk())
                    // 次画面の遷移先がindex.htmlであることを確認
                .andExpect(view().name("index"))
                    // セッションに設定されたsesHashMapの値が正しいことを確認
                .andExpect(request().sessionAttribute("sesHashMap", createHashMap()))
                    // Modelオブジェクトにエラーが無いことを確認
                .andExpect(model().hasNoErrors());
    }

    /**
     * DemoControllerクラスのnextメソッドを確認するためのテスト
     */
    @Test
    public void nextTest() throws Exception {
        HashMap<String, List<String>> paramMap = createHashMap();

        // テスト対象メソッド(next)を実行
        MvcResult results = mockMvc.perform(
                    // セッションsesHashMapを設定し、nextメソッドを実行
                post("/next/").sessionAttr("sesHashMap", paramMap))
                    // HTTPステータスがOKであることを確認
                .andExpect(status().isOk())
                    // 次画面の遷移先がnext.htmlであることを確認
                .andExpect(view().name("next"))
                    // ModelオブジェクトのsessionListに設定される値が正しいことを確認
                .andExpect(model().attribute("sessionList", paramMap.get("key1")))
                    // Modelオブジェクトにエラーが無いことを確認
                .andExpect(model().hasNoErrors())
                .andReturn();

        // テスト対象メソッド(next)実施後のリクエストオブジェクトから、セッションを
        // 取得し、セッションが取得できないことを確認
        MockHttpServletRequest returnReq = results.getRequest();
        HttpSession afterSession = returnReq.getSession(false);
        assertNull(afterSession);
    }

    /**
     * セッションに設定するハッシュマップを生成する
     * @return 生成したハッシュマップ
     */
    private HashMap<String, List<String>> createHashMap(){
        HashMap<String, List<String>> hashMap = new HashMap<>();

        List<String> hashList1 = new ArrayList<>();
        hashList1.add("item1");
        hashList1.add("item2");
        hashList1.add("item3");
        hashMap.put("key1", hashList1);

        List<String> hashList2 = new ArrayList<>();
        hashList2.add("item4");
        hashList2.add("item5");
        hashMap.put("key2", hashList2);

        return hashMap;
    }
}
サラリーマン型フリーランスSEという働き方でお金の不安を解消しよう先日、「サラリーマン型フリーランスSE」という働き方を紹介するYouTube動画を視聴しましたので、その内容をご紹介します。 「サ...

サンプルプログラムの実行結果

JUnitテストクラスの実行結果は以下の通りで、テストが正常に実行されていることが確認できる。
サンプルプログラムの実行結果_1

サンプルプログラムの実行結果_2 サンプルプログラムの実行結果_3

要点まとめ

  • MockMvcを利用すると、Spring MVCの動作を再現できるため、コントローラクラスのテストを行うことができる。
  • MockMvcのperformメソッドでコントローラクラスのメソッドを実行でき、andExpectメソッドでコントローラクラスの動作検証が行える。