質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JUnit

JUnitは、Javaで開発されたプログラムのユニットテストを行うためのアプリケーションフレームワークです。簡単にプログラムのユニットテストを自動化することができ、結果もわかりやすく表示されるため効率的に開発時間を短縮できます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1769閲覧

例外テストの書き方について

tenpu

総合スコア40

JUnit

JUnitは、Javaで開発されたプログラムのユニットテストを行うためのアプリケーションフレームワークです。簡単にプログラムのユニットテストを自動化することができ、結果もわかりやすく表示されるため効率的に開発時間を短縮できます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2018/06/12 14:28

前提・実現したいこと

例外テストの記述方法について教えてください。

様々なインプットに対して、対応した例外を投げるテストを作成したいと考えています。

インプットと期待例外のパターンの組み合わせ次第で、書き方としてはいくつか方法があると思いますが、
試みて失敗したものを記載しますので、解決案を教えて頂ければ助かります。

テストメソッドにはinvokeを使用しており、できるだけ@ParameterizedTestで、記述したいと考えています。

よろしくお願いします。

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

1. 異なるインプットに対して、全て同じ例外を返す場合 > テストメソッド:@ParameterizedTest宣言し、dataProvider部に'テストデータ'を記述する (メソッド引数:テストデータを渡す) →[問題] @Test(expected = xxException.class)のように、@ParameterizedTest宣言できない。 @ParameterizedTest(xxx) testMethod(testData){     〜 xxx.invoke(); } 2. 異なるインプットに対して、対応した例外を返す場合(例外パターンは複数) > テストメソッド:@Rule、@ParameterizedTest宣言し、dataProvider部に'テストデータ'と期待exceptionを記述する (メソッド引数:'テストデータ'と'期待exception.class'を渡す) →[問題] Ruleが機能していない。expected exception @Rule public ExpectedException thrown = ExpectedException.none(); @ParameterizedTest(xxx) testMethod(testData, zzz.class){ thrown.expect(zzz.class); 〜 xxx.invoke(); }

試したこと

try-catchの記述方法は、動作確認できております。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

これがテストとして書きやすいかどうかはわからないですが、とりあえずこんな感じではできそうです。

Calculatorクラス

java

1public class Calculator { 2 private int exception_div(Integer first, Integer second) { 3 return first / second; 4 } 5}

CalculatorTestクラス

java

1class CalculatorTests { 2 3 static Stream<Arguments> multiArgumentsProvider() { 4 return Stream.of(Arguments.of(null, 2, 50, NullPointerException.class), 5 Arguments.of(100, 0, -1, ArithmeticException.class), 6 // 3番目のケースでは例外が起きないのでテスト失敗します 7 Arguments.of(100, 2, 50, ArithmeticException.class)); 8 } 9 10 11 @ParameterizedTest(name = "{0} / {1} = {2}") 12 @MethodSource("multiArgumentsProvider") 13 void div(Integer first, Integer second, int expectedResult, Class<Exception> expectedException)  throws NoSuchMethodException, SecurityException { 14 15 Calculator calculator = new Calculator(); 16 Method method = Calculator.class.getDeclaredMethod("exception_div", Integer.class, Integer.class); 17 method.setAccessible(true); 18 19 InvocationTargetException exception = assertThrows(InvocationTargetException.class, () -> { 20 method.invoke(calculator, first, second); 21 }); 22 assertEquals(exception.getTargetException().getClass().toString(), expectedException.toString()); 23 } 24 25}

投稿2018/06/13 07:03

euledge

総合スコア2404

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

tenpuさんの希望されているのはこんな感じでしょうか?
JUnit5での記述です。

java

1import java.util.stream.Stream; 2 3import org.junit.jupiter.api.Assertions; 4import org.junit.jupiter.params.ParameterizedTest; 5import org.junit.jupiter.params.provider.Arguments; 6import org.junit.jupiter.params.provider.MethodSource; 7 8class CalculatorTests { 9 10 static Stream<Arguments> multiArgumentsProvider() { 11 return Stream.of( 12 Arguments.of(null, 2, 50, NullPointerException.class), 13 Arguments.of(100, 0, -1, ArithmeticException.class), 14 // 3番目のケースでは例外が起きないのでテスト失敗します 15 Arguments.of(100, 2, 50, ArithmeticException.class) 16 ); 17 } 18 19 @ParameterizedTest(name = "{0} / {1} = {2}") 20 @MethodSource("multiArgumentsProvider") 21 void div(Integer first, Integer second, int expectedResult, Class<Exception> expectedException) { 22 Assertions.assertThrows(expectedException, () -> { 23 System.out.println(first / second); 24 }); 25 } 26}

投稿2018/06/12 15:59

編集2018/06/12 16:11
euledge

総合スコア2404

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tenpu

2018/06/13 02:57

ありがとうございます。 assertThrowsは良さそうな感じがしますが、 () -> {)部がreflectionのinvoke()先でエラーになった場合は、テスト対象メソッドで発生したexceptionではないラップされたexceptionが返ってくることになり、assert期待値のexceptionではなくなると思います。 これに関しては、どのように対応すれば良いでしょうか?
euledge

2018/06/13 03:17

テストを行うのは 例外を発生するメソッドの挙動ですよね。 運用レベルで抽象化するためにリフレクションするのはいいと思うのですが、例外を発生するメソッドをテストするときには実体でよいのではないかと思います。 リフレクション出来ているかどうかはまた別のテストですればよいのかと思いますがどうでしょう? ひとつのテストで全部やろうとしないほうがシンプルに捉えられると思います。
tenpu

2018/06/13 03:59

はい。 テストメソッドがprivateなので、reflectionを使用しているのですが、他にやり方はありますでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問