web-dev-qa-db-ja.com

JUnitで例外を処理する方法

メソッドをテストするために、いくつかのテストケースを作成しました。ただし、一部のメソッドは例外をスローします。正しくやっていますか?

_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...)のような特定の例外をテストすることはできません

26
Sammy Pawar

予期しない例外はテストの失敗であるため、テストする必要はありません。

@Test
public void canConvertStringsToDecimals() {
    String str = "1.234";
    Assert.assertEquals(1.234, service.convert(str), 1.0e-4);
}

serviceに小数点があるため、IllegalArgumentExceptionstrをスローしない限り、単純なテストの失敗になります。

予想される例外は、@Testのオプションのexpected引数で処理する必要があります。

@Test(expected=NullPointerException.class)
public void cannotConvertNulls() {
    service.convert(null);
}

プログラマーが怠けてExceptionを投げた場合、またはservice return 0.0を持っている場合、テストは失敗します。 NPEのみが成功します。予期される例外のサブクラスも機能することに注意してください。これはNPEsではまれですが、IOExceptionsおよびSQLExceptionsでは一般的です。

特定の例外メッセージをテストするまれなケースでは、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;をインライン化できます。今では、あまり役に立ちません。これをパラメータ化されたテストクラスに変えることができます。

48
Eric Jablow

テストに失敗するために例外をキャッチする必要はありません。 (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
  }
}

この種のテストを使用して、コードが入力を適切に検証しているかどうかを検証し、適切な例外を使用して無効な入力を処理できます。

7
javadeveloper

テストで予想される例外に対処するために、いくつかの戦略が用意されています。 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

3
raghera