Mockitoのバージョンが2の場合、MockMakerファイルを配置すれば、finalメソッドをMock化することができる。今回は、MockMakerファイルを配置した上で、finalメソッドをMock化するサンプルプログラムを作成してみたので、共有する。
前提条件
下記記事の実装が完了していること。
また、以下のように、Mockitoのバージョンが2であること。
作成したサンプルプログラムの内容と実行結果
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠は、前提条件のプログラムから変更したプログラムである。
src/mainフォルダ下の変更したプログラムの内容は以下の通りで、コントローラクラスで、finalメソッドとfinalでないメソッドの両方を呼び出している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package com.example.demo; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @Component public class DemoComponent { /** * 現在日時を取得し返却する * @return 現在日時 */ public String getNowDateTime(){ LocalDateTime nowDateTime = LocalDateTime.now(); return nowDateTime.toString(); } /** * finalメソッドで現在日時を取得し返却する * @return 現在日時 */ public final String getNowDateTimeFinal(){ LocalDateTime nowDateTime = LocalDateTime.now(); return nowDateTime.toString(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class DemoController { /** * DemoComponentクラス */ @Autowired DemoComponent demoComponent; /** * 初期表示画面に遷移する * @param model Modelオブジェクト * @return 初期表示画面へのパス */ @RequestMapping("/") public String index(Model model){ String nowDateTime = demoComponent.getNowDateTime(); String nowDateTimeFinal = demoComponent.getNowDateTimeFinal(); model.addAttribute("nowDateTime", nowDateTime); model.addAttribute("nowDateTimeFinal", nowDateTimeFinal); return "index"; } } |
1 2 3 4 5 6 7 8 9 10 11 | <!DOCTYPE html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>index page</title> </head> <body> nowDateTimeの値: <span th:text="${nowDateTime}">nowDateTimeの値</span><br/><br/> nowDateTimeFinalの値: <span th:text="${nowDateTimeFinal}">nowDateTimeFinalの値</span> </body> </html> |
上記ソース内容で、 Spring Bootアプリケーションを起動し、「http:// (ホスト名):(ポート番号)」とアクセスすると、以下の画面が表示される。
また、MockMakerのファイルは以下のように、「src/test/resources/mockito-extensions」フォルダ下に、「org.mockito.plugins.MockMaker」というファイル名で作成し、そのファイルに「mock-maker-inline」と記載する必要がある。
さらに、コントローラクラスのテストを行うプログラムの内容は以下の通りで、finalメソッドであるgetNowDateTimeFinalメソッドも、finalメソッドでないgetNowDateTimeメソッドも、Mock化できている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | package com.example.demo; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.springframework.ui.Model; import java.time.LocalDateTime; import java.util.Map; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; public class DemoControllerTest { /** * テスト対象のクラス */ @InjectMocks private DemoController demoController; /** * テスト対象のクラス内で呼ばれるクラスのMockオブジェクト */ @Mock private DemoComponent demoComponent; /** * 前処理(各テストケースを実行する前に行われる処理) */ @Before public void init(){ //@Mockアノテーションのモックオブジェクトを初期化 //これを実行しないと@Mockアノテーション、@InjectMocksを付与した //Mockオブジェクトが利用できない MockitoAnnotations.initMocks(this); //Mockの設定 when(demoComponent.getNowDateTime()).thenReturn(getNowDateTimeStr()); when(demoComponent.getNowDateTimeFinal()).thenReturn(getNowDateTimeStr()); } /** * DemoControllerクラスのindexメソッドを確認 */ @Test public void testDemoController(){ //Modelオブジェクトを生成 Model model = DemoControllerTestUtil.getModel(); //テスト対象クラスのメソッドを実行 String strPath = demoController.index(model); //テスト対象クラスのメソッドで設定されたMapオブジェクトを表示 System.out.println(); System.out.println("*** コントローラクラスのindexメソッドで設定されたMapオブジェクト ***"); System.out.println(model.asMap()); System.out.println(); //テスト対象クラスのメソッドの実行結果を確認 assertEquals("index", strPath); Map<String, Object> mapObj = model.asMap(); assertEquals("2020-07-14T20:54:12", mapObj.get("nowDateTime")); assertEquals("2020-07-14T20:54:12", mapObj.get("nowDateTimeFinal")); } /** * 現在時刻を生成し文字列化して返却 * @return 現在時刻の文字列 */ private String getNowDateTimeStr(){ LocalDateTime nowDateTime = LocalDateTime.of( 2020, 7, 14, 20, 54, 12); return nowDateTime.toString(); } } |
また、Modelオブジェクトを生成し返却するプログラムの内容は以下の通りで、先ほどのDemoControllerTestクラスで呼び出している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | package com.example.demo; import org.springframework.ui.Model; import java.util.Collection; import java.util.HashMap; import java.util.Map; public class DemoControllerTestUtil { /** * Modelオブジェクトを生成し返却する * @return Modelオブジェクト */ public static Model getModel(){ return new Model() { private Map<String, Object> modelMap = new HashMap<>(); @Override public Model addAttribute(String attributeName, Object attributeValue) { modelMap.put(attributeName, attributeValue); return null; } @Override public Model addAttribute(Object attributeValue) { return null; } @Override public Model addAllAttributes(Collection<?> attributeValues) { return null; } @Override public Model addAllAttributes(Map<String, ?> attributes) { return null; } @Override public Model mergeAttributes(Map<String, ?> attributes) { return null; } @Override public boolean containsAttribute(String attributeName) { return false; } @Override public Map<String, Object> asMap() { return modelMap; } }; } } |
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/junit-mockito-final/demo
DemoControllerTestクラスを実行した結果は以下の通りで、finalメソッドであるgetNowDateTimeFinalメソッドも、finalメソッドでないgetNowDateTimeメソッドも、Mock化により返却された値が設定されることが確認できる。
要点まとめ
- Mockitoのバージョンが2の場合、MockMakerファイルを配置すれば、finalメソッドをMock化することができる。
- MockMakerのファイルは「src/test/resources/mockito-extensions」フォルダ下に「org.mockito.plugins.MockMaker」というファイル名で作成し、そのファイルに「mock-maker-inline」と記載すればよい。