メソッドをテストするために、いくつかのテストケースを作成しました。ただし、一部のメソッドは例外をスローします。正しくやっていますか?
_private void testNumber(String Word, int number) {
try {
assertEquals(Word, service.convert(number));
} catch (OutOfRangeNumberException e) {
Assert.fail("Test failed : " + e.getMessage());
}
}
@Test
public final void testZero() {
testNumber("zero", 0);
}
_
_-45
_を渡すと、OutOfRangeException
で失敗しますが、@Test(Expected...)
のような特定の例外をテストすることはできません
予期しない例外はテストの失敗であるため、テストする必要はありません。
@Test
public void canConvertStringsToDecimals() {
String str = "1.234";
Assert.assertEquals(1.234, service.convert(str), 1.0e-4);
}
service
に小数点があるため、IllegalArgumentException
がstr
をスローしない限り、単純なテストの失敗になります。
予想される例外は、@Test
のオプションのexpected
引数で処理する必要があります。
@Test(expected=NullPointerException.class)
public void cannotConvertNulls() {
service.convert(null);
}
プログラマーが怠けてException
を投げた場合、またはservice
return 0.0
を持っている場合、テストは失敗します。 NPE
のみが成功します。予期される例外のサブクラスも機能することに注意してください。これはNPE
sではまれですが、IOException
sおよびSQLException
sでは一般的です。
特定の例外メッセージをテストするまれなケースでは、newish ExpectedException
JUnit @Rule
を使用します。
@Rule
public ExpectedException thrown= ExpectedException.none();
@Test
public void messageIncludesErrantTemperature() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("-400"); // Tests that the message contains -400.
temperatureGauge.setTemperature(-400);
}
現在、setTemperatureがIAE
をスローし、メッセージにユーザーが設定しようとした温度が含まれていない限り、テストは失敗します。このルールは、より洗練された方法で使用できます。
あなたの例は、次の方法で最適に処理できます。
private void testNumber(String Word, int number)
throws OutOfRangeNumberException {
assertEquals(Word, service.convert(number));
}
@Test
public final void testZero()
throws OutOfRangeNumberException {
testNumber("zero", 0);
}
testNumber
;をインライン化できます。今では、あまり役に立ちません。これをパラメータ化されたテストクラスに変えることができます。
テストに失敗するために例外をキャッチする必要はありません。 (throws
を宣言して)そのままにしておけば、それでも失敗します。
別のケースとして、実際に例外を予期している場合、tryブロックの最後にfailを配置します。
例えば:
@Test
public void testInvalidNumber() {
try {
String dummy = service.convert(-1));
Assert.fail("Fail! Method was expected to throw an exception because negative numbers are not supported.")
} catch (OutOfRangeException e) {
// expected
}
}
この種のテストを使用して、コードが入力を適切に検証しているかどうかを検証し、適切な例外を使用して無効な入力を処理できます。
テストで予想される例外に対処するために、いくつかの戦略が用意されています。 JUnitアノテーションとtry/catchイディオムについては、すでに上で述べたと思います。 Lambda式のJava 8オプションに注目してください。
たとえば、次のとおりです。
class DummyService {
public void someMethod() {
throw new RuntimeException("Runtime exception occurred");
}
public void someOtherMethod(boolean b) {
throw new RuntimeException("Runtime exception occurred",
new IllegalStateException("Illegal state"));
}
}
あなたはこれを行うことができます:
@Test
public void verifiesCauseType() {
// lambda expression
assertThrown(() -> new DummyService().someOtherMethod(true))
// assertions
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasCauseInstanceOf(IllegalStateException.class);
}
ほとんどのオプションと例を挙げたこのブログをご覧ください。
http://blog.codeleak.pl/2013/07/3-ways-of-handling-exceptions-in-junit.html
そして、これはJava 8 Lambdaオプションをより完全に説明しています:
http://blog.codeleak.pl/2014/07/junit-testing-exception-with-Java-8-and-lambda-expressions.html