staticメソッドについても、PowerMockを利用すれば、例外を発生させるJUnitプログラムを作成できる。今回は、PowerMockを利用して、下記「前提条件」とサンプルプログラムを作成してみたので、共有する。
前提条件
下記記事の実装が完了していること。
JUnitのMockitoで例外処理のテストをしてみたMockitoを利用すると、例外を発生させるMockプログラムも作成することができる。
今回は例外処理を含むプログラムをテストするJU...
やってみたこと
テスト対象プログラムの作成と実行
作成したサンプルプログラムの構成は以下の通り。
なお、上図の赤枠は、前提条件のプログラムから変更した内容である。
テスト対象のコントローラクラスの内容は以下の通り。
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 | package com.example.demo; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.io.FileNotFoundException; @Controller public class DemoController { @RequestMapping("/") public String index(Model model){ String textString; try{ textString = DemoUtil.getTextString(); }catch (Exception e){ String errMsg; if(e instanceof FileNotFoundException){ errMsg = "ファイルが見つかりませんでした"; }else{ errMsg = "入出力例外が発生しました"; } //エラー時はerror.htmlに遷移 model.addAttribute("errMsg", errMsg); return "error"; } //正常時はindex.htmlに遷移 model.addAttribute("textString", textString); return "index"; } } |
また、上記プログラムから呼び出されるユーティリティクラスの内容は以下の通りで、staticメソッドになっている。
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 java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class DemoUtil { public static String getTextString() throws IOException{ StringBuilder sb = new StringBuilder(); try(BufferedReader br = new BufferedReader( new FileReader("C:\\tmp\\test.txt"))) { String line; while ((line = br.readLine()) != null) { sb.append(line); } }catch (FileNotFoundException ex1){ throw ex1; }catch (IOException ex2){ throw ex2; } return sb.toString(); } } |
さらに、本プログラムを実行した結果は、前提条件の記事の「テスト対象プログラムの実行」に記載した通りとなる。
JUnitのプログラムの作成と実行
build.gradleの内容は以下の通り。PowerMockが利用できるための設定を追加している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | plugins { id 'org.springframework.boot' version '2.1.7.RELEASE' id 'java' } apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' //PowerMockが利用できるための設定 testCompile 'org.powermock:powermock-module-junit4:2.0.0-RC.4' testCompile 'org.powermock:powermock-api-mockito2:2.0.0-RC.4' } |
また、テスト対象のコントローラクラス「DemoController.java」から呼ばれるユーティリティクラス「DemoUtil.java」で例外を発生させた場合の、JUnitのサンプルプログラムの内容は以下の通り。
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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | package com.example.demo; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import org.mockito.MockitoAnnotations; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.springframework.ui.Model; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Map; //staticメソッドをMock化するにはPowerMockを利用 //@PrepareForTestアノテーションで、staticメソッドを含むクラスを指定 @RunWith(PowerMockRunner.class) @PrepareForTest({DemoUtil.class}) public class DemoControllerTest { /** * テスト対象クラス */ @InjectMocks private DemoController demoController; /** * 前処理(各テストケースを実行する前に行われる処理) */ @Before public void init() { //@Mockアノテーションのモックオブジェクトを初期化 //これを実行しないと@Mockアノテーション、@InjectMocksを付与した //Mockオブジェクトが利用できない MockitoAnnotations.initMocks(this); //DemoUtilクラスをMock化 PowerMockito.mockStatic(DemoUtil.class); } /** * DemoControllerクラスのindexメソッドの確認 */ @Test public void testDemoControllerNormal() throws Exception { //Mockオブジェクト呼出時の戻り値を設定(DemoUtil.java) //when句に(staticメソッドをもつ)クラス名・staticメソッド名・引数を順に //指定するが例外が発生し得るため、「throws Exception」を付与する PowerMockito.doReturn("abcdeテスト") .when(DemoUtil.class, "getTextString"); //modelオブジェクトを取得し、テスト対象クラスのメソッドを実行 Model model = DemoControllerTestUtil.getModel(); String returnVal = demoController.index(model); //戻り値が"index"であることを確認 assertEquals("index", returnVal); //modelオブジェクトの設定値を確認 //demoComponent.getTextStringが呼ばれた場合は設定したMockの戻り値が設定され、 //エラーメッセージが設定されないことを確認 Map<String, Object> modelValue = model.asMap(); assertEquals("abcdeテスト", modelValue.get("textString")); assertNull(modelValue.get("errMsg")); } @Test public void testDemoControllerNotFoundException() throws Exception { //Mockオブジェクト呼出時の例外を設定(DemoUtil.java) //doThrow句内に例外を設定するが、発生し得ない例外(例:Exception)は設定できない PowerMockito.doThrow(new FileNotFoundException()) .when(DemoUtil.class, "getTextString"); //modelオブジェクトを取得し、テスト対象クラスのメソッドを実行 Model model = DemoControllerTestUtil.getModel(); String returnVal = demoController.index(model); //戻り値が"error"であることを確認 assertEquals("error", returnVal); //modelオブジェクトの設定値を確認 //FileNotFoundExceptionが発生した場合のエラーメッセージ //「ファイルが見つかりませんでした」が設定され、 //textStringが設定されないことを確認 Map<String, Object> modelValue = model.asMap(); assertEquals("ファイルが見つかりませんでした", modelValue.get("errMsg")); assertNull(modelValue.get("textString")); } @Test public void testDemoControllerIOException() throws Exception { //Mockオブジェクト呼出時の例外を設定(DemoUtil.java) //doThrow句内に例外を設定するが、発生し得ない例外(例:Exception)は設定できない PowerMockito.doThrow(new IOException()) .when(DemoUtil.class, "getTextString"); //modelオブジェクトを取得し、テスト対象クラスのメソッドを実行 Model model = DemoControllerTestUtil.getModel(); String returnVal = demoController.index(model); //戻り値が"error"であることを確認 assertEquals("error", returnVal); //modelオブジェクトの設定値を確認 //IOExceptionが発生した場合のエラーメッセージ「入出力例外が発生しました」が //設定され、textStringが設定されないことを確認 Map<String, Object> modelValue = model.asMap(); assertEquals("入出力例外が発生しました", modelValue.get("errMsg")); assertNull(modelValue.get("textString")); } } |
上記の「testDemoControllerNotFoundException」「testDemoControllerIOException」メソッドのように、PowerMockito.doThrow句を利用することで、指定したクラスの指定したstaticメソッドを実行した際に、指定した例外がスローされるようにMock設定できる。
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/junit-powermock-exception/demo
要点まとめ
- PowerMockito.doThrow句を利用することで、指定したクラスの指定したstaticメソッドを実行した際に、指定した例外がスローされるようにMock設定できる。