77

予想される例外でメソッドをテストしています。また、例外がスローされた後にクリーンアップ コードが (モック オブジェクトで) 呼び出されたことを確認する必要がありますが、その確認は無視されているようです。これがコードです。JunitExpectedException Ruleを使用して、予想される例外を確認しています。

@Rule
public ExpectedException expectedEx = ExpectedException.none();

@Test
public void testExpectedException()
{
   MockedObject mockObj = mock(MockedObj.class);
   MySubject subject = new MySubject(mockedObj);
   expectedEx.expect(MyException.class);
   expectedEx.expectMessage("My exception message.");
   subject.someMethodThrowingException();
   verify(mockObj).
       someCleanup(eq(...));
}

verifyは完全に無視されているようです。にどのメソッドを入れてもverify、テストはパスしますが、これは私が望んでいるものではありません。

なぜそれが起こっているのですか?

4

4 に答える 4

87

ExpectedExceptionJUnit @Ruleを介して、テスト メソッド全体を try-catch ブロックにラップすることで機能します。コードが例外をスローすると、スタックを最も近い try/catch に移動します。これはたまたま ExpectedException インスタンスにある (予期した例外であることを確認します)。

Java では、キャッチされない例外がメソッド内で発生した場合、そのメソッド内の後のステートメントに制御が戻ることはありません。ここでも同じルールが適用されます。例外の後、テスト内のステートメントに制御が戻ることはありません。

技術的には、検証を finally ブロックに入れることもできますが、それは悪い習慣になりがちです。編集:テスト対象のシステムが予期しない例外をスローするか、例外をまったくスローしない可能性があります。これにより、役立つエラー メッセージとトレースが得られます。ただし、その失敗によりfinallyブロック内の検証またはアサーションが失敗した場合、Java は、予期しない例外または予期しない成功に関するメッセージではなく、それを表示します。これにより、デバッグが困難になる可能性があります。特に、エラーの根本原因に続くコード行からエラーが発生し、その上のコードが成功したことを誤って示唆するためです。

メソッドごとに例外後の状態を本当に確認する必要がある場合は、いつでもこのイディオムに戻すことができます。

@Test
public void testExpectedException()
{
  MockedObject mockObj = mock(MockedObj.class);
  MySubject subject = new MySubject(mockedObj);
  try {
    subject.someMethodThrowingException();
    fail("Expected MyException.");
  } catch (MyException expected) {
    assertEquals("My exception message.", expected.getMessage());
  }
  verify(mockObj).someCleanup(eq(...));
}

更新: Java 8 のラムダ式を使用すると、関数型インターフェイスの呼び出しを try ブロックで十分に簡潔にラップできます。この構文のサポートは、多くの標準的なテスト ライブラリに導入されると思います。

assertThrows(MyException.class,
    () -> systemUnderTest.throwingMethod());
于 2012-11-05T00:48:56.403 に答える
4

私はまだこれを試していませんが、Jeff Bowman の優れた回答に加えて、try... finally コンストラクトで ExpectedException ルールを使用し、verify ステートメントを finally ブロックに配置するという選択肢があるかもしれません。

于 2012-11-05T02:59:29.550 に答える