1. ホーム
  2. java

例外発生後のMockitoの検証 Junit 4.10

2023-08-28 14:19:38

質問

予想される例外が発生するメソッドをテストしています。私はまた、例外が投げられた後にいくつかのクリーンアップコードが(モックされたオブジェクト上で)呼び出されたことを確認する必要がありますが、その検証は無視されているように見えます。以下はそのコードです。私はJunitの ExpectedException 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 にどんなメソッドを入れても、私のテストはパスします。

なぜそれが起こっているのか、何か考えがありますか?

どのように解決するのですか?

ExpectedException で動作します。 でテストメソッド全体を囲みます。 をtry-catchブロックの中で JUnit の @Rule . コードが例外を投げると、スタックを上がって一番近いtry/catchに行き、たまたまExpectedExceptionのインスタンスにあります(期待する例外であることをチェックします)。

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

技術的には、最終ブロックの中に検証を入れることもできますが、その場合は 悪い習慣 . となります。 EDIT テスト中のシステムが予期せぬ例外を発生させたり、まったく例外が発生しなかったりした場合、有用な失敗メッセージやトレースが得られます。 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());