web-dev-qa-db-ja.com

JUnit 4のテストで特定の例外がスローされたとどのように主張しますか?

JUnit4を慣用的に使用して一部のコードで例外がスローされることをテストする方法を教えてください。

私は確かにこのようなことをすることができますが:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  boolean thrown = false;

  try {
    foo.doStuff();
  } catch (IndexOutOfBoundsException e) {
    thrown = true;
  }

  assertTrue(thrown);
}

私は、アノテーションやAssert.xyzあるいは なにか があることを思い出してください。これらは、このような状況では、あまり意味がなく、JUnitの精神をはるかに超えています。

1824
SCdF

JUnit 4はこれをサポートしています。

@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
    ArrayList emptyList = new ArrayList();
    Object o = emptyList.get(0);
}

参照: https://junit.org/junit4/faq.html#atests_7

2190
skaffman

編集 JUnit5がリリースしたので、最良の選択肢はAssertions.assertThrows()を使うことです( 私の他の答え を参照)。

JUnit 5に移行していなくてもJUnit 4.7を使用できる場合は、 ExpectedException Ruleを使用できます。

public class FooTest {
  @Rule
  public final ExpectedException exception = ExpectedException.none();

  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    exception.expect(IndexOutOfBoundsException.class);
    foo.doStuff();
  }
}

@Test(expected=IndexOutOfBoundsException.class)の前にIndexOutOfBoundsExceptionがスローされるとテストは失敗するので、これはfoo.doStuff()よりはるかに優れています。

詳細は この記事 を参照してください。

1244
NamshubWriter

テストでは method がその例外を投げたことを表明しているだけであり、 特定のコード行 は表明していないことを表明しているので、予想される例外の使用に注意してください。

このようなメソッドは通常非常に単純ですが、より複雑なテストの方が適している可能性があるため、パラメーターの検証をテストするためにこれを使用する傾向があります。

try {
    methodThatShouldThrow();
    fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}

判断を下す。

445
daveb

前に答えたように、JUnitの例外を扱う方法はたくさんあります。しかし、Java 8にはもう1つあります。それは、ラムダ式の使用です。ラムダ式を使用すると、次のような構文を実現できます。

@Test
public void verifiesTypeAndMessage() {
    assertThrown(new DummyService()::someMethod)
            .isInstanceOf(RuntimeException.class)
            .hasMessage("Runtime exception occurred")
            .hasMessageStartingWith("Runtime")
            .hasMessageEndingWith("occurred")
            .hasMessageContaining("exception")
            .hasNoCause();
}

assertThrownは、ラムダ式、メソッド参照、またはコンストラクタ参照を使用してインスタンスを作成できる機能的インタフェースを受け入れます。そのインターフェイスを受け入れるassertThrownは、例外を予期して処理する準備ができています。

これは比較的単純だが強力なテクニックです。

このテクニックを説明しているこのブログ記事を見てみましょう: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-Java-8-and-lambda-expressions.html

ソースコードはここにあります: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/Java/com/github/kolorobot/exceptions/Java8

開示:私はブログとプロジェクトの著者です。

202
Rafal Borowiec

ちなみに、例外をテストする方法は4つあります。

  • junit4.xの場合は、Test annonationのオプションの 'expected'属性を使用します。

    @Test(expected = IndexOutOfBoundsException.class)
    public void testFooThrowsIndexOutOfBoundsException() {
        foo.doStuff();
    }
    
  • junit4.xの場合は、ExpectedExceptionルールを使用します。

    public class XxxTest {
        @Rule
        public ExpectedException thrown = ExpectedException.none();
    
        @Test
        public void testFooThrowsIndexOutOfBoundsException() {
            thrown.expect(IndexOutOfBoundsException.class)
            //you can test the exception message like
            thrown.expectMessage("expected messages");
            foo.doStuff();
        }
    }
    
  • あなたはまた、junit 3フレームワークの下で広く使われている古典的なtry/catch方法を使うことができます。

    @Test
    public void testFooThrowsIndexOutOfBoundsException() {
        try {
            foo.doStuff();
            fail("expected exception was not occured.");
        } catch(IndexOutOfBoundsException e) {
            //if execution reaches here, 
            //it indicates this exception was occured.
            //so we need not handle it.
        }
    }
    
  • 最後に、junit5.xでは、以下のようにassertThrowsを使うこともできます。

    @Test
    public void testFooThrowsIndexOutOfBoundsException() {
        Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff());
        assertEquals("expected messages", exception.getMessage());
    }
    
  • そう

    • 1番目の方法は、例外の種類をテストするだけの場合に使用されます。
    • 例外メッセージをさらにテストしたい場合は、他の3つの方法が使用されます。
    • あなたがjunit 3を使っているなら、3番目のものが優先されます。
    • あなたがjunit 5が好きなら、あなたは4番目のものが好きです
  • 詳細については、 このドキュメント および junit5のユーザーガイド を参照してください。

108
walsh

tl; dr

  • jDK8より前:古い良いtry-catchブロックをお勧めします。 (catchブロックの前にfail()アサーションを追加することを忘れないでください

  • post-JDK8:AssertJまたはカスタムラムダを使用してexceptional動作をアサートします。

Junit 4またはJUnit 5に関係なく

長い話

自分で自分でやるtry-catchブロックを記述するか、JUnitツール(@Test(expected = ...)または@Rule ExpectedException JUnitルール機能)を使用することができます。

しかし、これらの方法はそれほどエレガントではなく、readability wise他のツールとうまく混ざりません。さらに、JUnitツールにはいくつかの落とし穴があります。

  1. try-catchブロックは、テストされた動作の周りにブロックを記述し、catchブロックにアサーションを記述する必要があります。これは問題ないかもしれませんが、多くの場合、このスタイルはテストの読み取りフローを中断します。また、tryブロックの最後にAssert.failを記述する必要があります。そうしないと、テストがアサーションの片側を見逃す可能性があります。 PMDfindbugsまたはSonarはそのような問題を発見します。

  2. @Test(expected = ...)機能は、より少ないコードを記述でき、このテストを記述することでコーディングエラーが発生する可能性が低いため、興味深いものです。 しかしこのアプローチにはいくつかの領域が欠けています。

    • テストで原因やメッセージなどの例外に関する追加事項を確認する必要がある場合(適切な例外メッセージは本当に重要であり、正確な例外タイプでは不十分な場合があります)。
    • また、メソッドに期待が置かれているため、テストされたコードの記述方法に応じて、テストコードの間違った部分が例外をスローし、誤検知テストにつながる可能性がありますPMDfindbugsまたはSonarは、そのようなコードに関するヒントを提供します。

      @Test(expected = WantedException.class)
      public void call2_should_throw_a_WantedException__not_call1() {
          // init tested
          tested.call1(); // may throw a WantedException
      
          // call to be actually tested
          tested.call2(); // the call that is supposed to raise an exception
      }
      
  3. ExpectedExceptionルールは、以前の警告を修正する試みでもありますが、期待スタイルを使用しているため、使用するのは少し厄介です。EasyMockユーザーはこのスタイルをよく知っています。一部の人にとっては便利かもしれませんが、行動駆動開発(BDD)またはアレンジアサート(AAA)の原則に従うと、ExpectedExceptionルールはこれらの記述スタイルに適合しません。 。それ以外に、期待する場所に応じて、@Testウェイと同じ問題が発生する可能性があります。

    @Rule ExpectedException thrown = ExpectedException.none()
    
    @Test
    public void call2_should_throw_a_WantedException__not_call1() {
        // expectations
        thrown.expect(WantedException.class);
        thrown.expectMessage("boom");
    
        // init tested
        tested.call1(); // may throw a WantedException
    
        // call to be actually tested
        tested.call2(); // the call that is supposed to raise an exception
    }
    

    予想される例外がテストステートメントの前に置かれたとしても、テストがBDDまたはAAAに従っている場合、読み取りフローが中断されます。

    ExpectedExceptionの作者のJUnitに関するこの comment の問題も参照してください。 JUnit 4.13-beta-2 は、このメカニズムを非推奨にします:

    プルリクエスト#1519 :ExpectedExceptionの廃止

    Assert.assertThrowsメソッドは、例外を検証するためのより良い方法を提供します。さらに、TestWatcherなどの他のルールでExpectedExceptionを使用するとエラーが発生しやすくなります。その場合、ルールの順序が重要だからです。

したがって、上記のオプションにはすべての注意事項があり、明らかにコーダーエラーの影響を受けません。

  1. この回答を作成した後に気付いたプロジェクトは有望に見えます。 catch-exception です。

    プロジェクトの説明にあるように、例外をキャッチする流exceptionなコード行をコーダーに記述させ、この例外を後のアサーションに提供します。また、 HamcrestAssertJ などのアサーションライブラリを使用できます。

    ホームページから取られた迅速な例:

    // given: an empty list
    List myList = new ArrayList();
    
    // when: we try to get the first element of the list
    when(myList).get(1);
    
    // then: we expect an IndexOutOfBoundsException
    then(caughtException())
            .isInstanceOf(IndexOutOfBoundsException.class)
            .hasMessage("Index: 1, Size: 0") 
            .hasNoCause();
    

    コードが実に簡単であることがわかるように、特定の行で例外をキャッチします。then APIは、AssertJ APIを使用するエイリアスです(assertThat(ex).hasNoCause()...の使用に似ています)。 ある時点で、プロジェクトはAssertJの祖先であるFEST-Assertに依存していました編集:プロジェクトがJava 8 Lambdasサポートを作成しているようです。

    現在、このライブラリには2つの欠点があります。

    • この記事を書いている時点では、このライブラリはMockito 1.xに基づいていると言うことは注目に値する。 Mockitoはまだ更新されていないため、このライブラリはfinalクラスまたはfinalメソッドで動作しません。また、現在のバージョンのmockito 2に基づいていたとしても、このモックメーカーには通常のモックメーカーとは異なる欠点があるため、グローバルモックメーカー(inline-mock-maker)を宣言する必要があります。

    • さらに別のテスト依存関係が必要です。

    ライブラリがラムダをサポートすると、これらの問題は適用されませんが、機能はAssertJツールセットによって複製されます。

    catch-exceptionツールを使用したくない場合はすべて考慮して、少なくともJDK7までは、try-catchブロックの古い良い方法をお勧めします。また、JDK 8ユーザーの場合、AssertJは例外をアサートするだけではないため、AssertJの使用を好むかもしれません。

  2. JDK8では、ラムダがテストシーンに入り、例外的な動作をアサートする興味深い方法であることが証明されました。 AssertJは、例外的な動作をアサートするためのNice fluent APIを提供するように更新されました。

    AssertJ を使用したサンプルテスト:

    @Test
    public void test_exception_approach_1() {
        ...
        assertThatExceptionOfType(IOException.class)
                .isThrownBy(() -> someBadIOOperation())
                .withMessage("boom!"); 
    }
    
    @Test
    public void test_exception_approach_2() {
        ...
        assertThatThrownBy(() -> someBadIOOperation())
                .isInstanceOf(Exception.class)
                .hasMessageContaining("boom");
    }
    
    @Test
    public void test_exception_approach_3() {
        ...
        // when
        Throwable thrown = catchThrowable(() -> someBadIOOperation());
    
        // then
        assertThat(thrown).isInstanceOf(Exception.class)
                          .hasMessageContaining("boom");
    }
    
  3. JUnit 5のほぼ完全な書き直しにより、アサーションが少し 改善されました 、例外を適切にアサートするための独創的な方法として興味深いことがわかります。しかし、実際にはアサーションAPIはまだ少し貧弱で、 assertThrows の外には何もありません。

    @Test
    @DisplayName("throws EmptyStackException when peeked")
    void throwsExceptionWhenPeeked() {
        Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
    
        Assertions.assertEquals("...", t.getMessage());
    }
    

    お気づきのとおり、assertEqualsはまだvoidを返しているため、AssertJのようなアサーションのチェーンは許可されません。

    また、MatcherまたはAssertとの名前の衝突を覚えている場合は、Assertionsとの衝突に対応する準備をしてください。

今日(2017-03-03)AssertJの使いやすさ、発見可能なAPI、開発の迅速なペース、そしてde factoテスト依存性が最適であると結論付けたいテストフレームワーク(JUnitであるかどうかに関係なく)に関係なく、JDK8を使用するソリューションでは、以前のJDKは代わりにtry-catchブロックに依存する必要があります。

この回答は 別の質問 からコピーされ、同じ可視性はありません。私は同じ著者です。

102
Brice

JUnit 5がリリースしたので、最良の選択肢はAssertions.assertThrows()を使うことです( Junit 5ユーザーガイド を参照)。

これは、例外がスローされたことを確認し、 Truth を使用して例外メッセージをアサートする例です。

public class FooTest {
  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    IndexOutOfBoundsException e = assertThrows(
        IndexOutOfBoundsException.class, foo::doStuff);

    assertThat(e).hasMessageThat().contains("woops!");
  }
}

他の回答のアプローチに対する利点は次のとおりです。

  1. JUnitに内蔵
  2. ラムダ内のコードが例外をスローしない場合は有用な例外メッセージを受け取り、それが別の例外をスローする場合はスタックトレースを受け取ります。
  3. 簡潔
  4. あなたのテストがArrange-Act-Assertに従うことを許可します
  5. どのコードが例外をスローすることを期待しているのかを正確に示すことができます。
  6. 予想される例外をthrows句に記載する必要はありません。
  7. 選択したアサーションフレームワークを使用して、キャッチした例外についてアサーションを作成できます。

JUnit 4.13では、同様のメソッドがorg.junit Assertに追加されます。

49
NamshubWriter

これはどうですか:非常に一般的な例外をキャッチし、それがcatchブロックの外に出ていることを確認してから、例外のクラスが想定どおりであることをアサートします。このアサートは、a)例外のタイプが間違っている場合(例えば、代わりにNull Pointerを受け取った場合)、およびb)例外がこれまでにスローされていない場合に失敗します。

public void testFooThrowsIndexOutOfBoundsException() {
  Throwable e = null;

  try {
    foo.doStuff();
  } catch (Throwable ex) {
    e = ex;
  }

  assertTrue(e instanceof IndexOutOfBoundsException);
}
40
Johan

_ bdd _ スタイルの解決策: JUnit 4 + キャッチ例外 + AssertJ

@Test
public void testFooThrowsIndexOutOfBoundsException() {

    when(foo).doStuff();

    then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);

}

ソースコード

依存関係

eu.codearte.catch-exception:catch-exception:1.3.3
34
MariuszS

JUnitと一緒に使用できる AssertJ アサーションを使用します。

import static org.assertj.core.api.Assertions.*;

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  Foo foo = new Foo();

  assertThatThrownBy(() -> foo.doStuff())
        .isInstanceOf(IndexOutOfBoundsException.class);
}

テストで予想される行が例外をスローすることを保証し、メッセージなどの例外に関する詳細を簡単に確認できるため、@Test(expected=IndexOutOfBoundsException.class)よりも優れています。

assertThatThrownBy(() ->
       {
         throw new Exception("boom!");
       })
    .isInstanceOf(Exception.class)
    .hasMessageContaining("boom");

Maven/Gradleの説明はこちら。

33
weston

同じ問題を解決するために、私は小さなプロジェクトを立ち上げました: http://code.google.com/p/catch-exception/ /

この小さなヘルパーを使って書く

verifyException(foo, IndexOutOfBoundsException.class).doStuff();

これは、JUnit 4.7のExpectedExceptionルールよりも詳細ではありません。 skaffmanが提供するソリューションと比較して、どのコード行で例外を予想するかを指定できます。これが助けになれば幸いです。

32
rwitzel

更新:JUnit5は例外のテストを改善しました:assertThrows

次の例は、次のとおりです。 Junit 5ユーザーガイド

 @Test
void exceptionTesting() {
    Throwable exception = assertThrows(IllegalArgumentException.class, () -> 
    {
        throw new IllegalArgumentException("a message");
    });
    assertEquals("a message", exception.getMessage());
}

JUnit 4を使ったオリジナルの回答=

例外がスローされたことをテストする方法はいくつかあります。私の投稿では以下のオプションについても議論しました JUnitを使って素晴らしい単体テストを書く方法

expectedパラメータ@Test(expected = FileNotFoundException.class)を設定します。

@Test(expected = FileNotFoundException.class) 
public void testReadFile() { 
    myClass.readFile("test.txt");
}

trycatchを使う

public void testReadFile() { 
    try {
        myClass.readFile("test.txt");
        fail("Expected a FileNotFoundException to be thrown");
    } catch (FileNotFoundException e) {
        assertThat(e.getMessage(), is("The file test.txt does not exist!"));
    }

}

ExpectedExceptionルールによるテスト.

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

@Test
public void testReadFile() throws FileNotFoundException {

    thrown.expect(FileNotFoundException.class);
    thrown.expectMessage(startsWith("The file test.txt"));
    myClass.readFile("test.txt");
}

例外テストの詳細については、 例外テスト用のJUnit4のwiki および bad.robot - 例外の予測JUnitルール をご覧ください。

29

またこれをすることができます:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
    try {
        foo.doStuff();
        assert false;
    } catch (IndexOutOfBoundsException e) {
        assert true;
    }
}
21
John Mikic

私見、JUnitで例外をチェックする最良の方法はtry/catch/fail/assertパターンです。

// this try block should be as small as possible,
// as you want to make sure you only catch exceptions from your code
try {
    sut.doThing();
    fail(); // fail if this does not throw any exception
} catch(MyException e) { // only catch the exception you expect,
                         // otherwise you may catch an exception for a dependency unexpectedly
    // a strong assertion on the message, 
    // in case the exception comes from anywhere an unexpected line of code,
    // especially important if your checking IllegalArgumentExceptions
    assertEquals("the message I get", e.getMessage()); 
}

assertTrueは一部の人にとっては少し強いかもしれないので、assertThat(e.getMessage(), containsString("the message");が望ましいかもしれません。

13
Alex Collins

JUnit 5ソリューション

@Test
void testFooThrowsIndexOutOfBoundsException() {    
  Throwable exception = expectThrows( IndexOutOfBoundsException.class, foo::doStuff );

  assertEquals( "some message", exception.getMessage() );
}

JUnit 5に関するその他の情報は http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions にあります。

12
Daniel Käfer

私はここで多くの方法を試しましたが、それらは複雑だったか、私の要求を完全には満たしていませんでした。実際、ヘルパーメソッドは非常に簡単に書くことができます。

public class ExceptionAssertions {
    public static void assertException(BlastContainer blastContainer ) {
        boolean caughtException = false;
        try {
            blastContainer.test();
        } catch( Exception e ) {
            caughtException = true;
        }
        if( !caughtException ) {
            throw new AssertionFailedError("exception expected to be thrown, but was not");
        }
    }
    public static interface BlastContainer {
        public void test() throws Exception;
    }
}

このように使用してください。

assertException(new BlastContainer() {
    @Override
    public void test() throws Exception {
        doSomethingThatShouldExceptHere();
    }
});

依存関係がない:モッキートが不要、パワーモックが不要そしてファイナルクラスでうまく動作します。

11
Hugh Perkins

Mkyongブログ で見つけたJunit 4の最も柔軟でエレガントな答え。 try/catchアノテーションを使用して@Ruleの柔軟性を持っています。カスタマイズされた例外の特定の属性を読み取ることができるので、私はこのアプローチが好きです。

package com.mkyong;

import com.mkyong.examples.CustomerService;
import com.mkyong.examples.exception.NameNotFoundException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasProperty;

public class Exception3Test {

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

    @Test
    public void testNameNotFoundException() throws NameNotFoundException {

        //test specific type of exception
        thrown.expect(NameNotFoundException.class);

        //test message
        thrown.expectMessage(is("Name is empty!"));

        //test detail
        thrown.expect(hasProperty("errCode"));  //make sure getters n setters are defined.
        thrown.expect(hasProperty("errCode", is(666)));

        CustomerService cust = new CustomerService();
        cust.findByName("");

    }

}
10
Dherik

Java 8ソリューション

あなたが解決策をご希望の場合:

  • Java 8のラムダを利用する
  • JUnitの魔法に依存しない
  • 単一のテストメソッド内で複数の例外をチェックできます
  • テストメソッド全体の未知の行ではなく、テストメソッド内の特定の行セットによって例外がスローされているかどうかを確認
  • さらに調べることができるように、スローされた実際の例外オブジェクトを返します。

これが私が書いた効用関数です。

public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
    try
    {
        runnable.run();
    }
    catch( Throwable throwable )
    {
        if( throwable instanceof AssertionError && throwable.getCause() != null )
            throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
        assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
        assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
        @SuppressWarnings( "unchecked" )
        T result = (T)throwable;
        return result;
    }
    assert false; //expected exception was not thrown.
    return null; //to keep the compiler happy.
}

私のブログから取った

次のように使用してください。

@Test
public void testThrows()
{
    RuntimeException e = expectException( RuntimeException.class, () -> 
        {
            throw new RuntimeException( "fail!" );
        } );
    assert e.getMessage().equals( "fail!" );
}
9
Mike Nakis
8
Mark Bessey

私の場合は、常にdbからRuntimeExceptionを受け取りますが、メッセージは異なります。そして、それぞれ例外を処理する必要があります。これが私がテストした方法です:

@Test
public void testThrowsExceptionWhenWrongSku() {

    // Given
    String articleSimpleSku = "999-999";
    int amountOfTransactions = 1;
    Exception exception = null;

    // When
    try {
        createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku);
    } catch (RuntimeException e) {
        exception = e;
    }

    // Then
    shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU);
}

private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) {
    assertNotNull(e);
    assertTrue(e.getMessage().contains(message));
}
7
Macchiatow

JUnit 4以降では、次のようにして例外をテストできます。

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


これは私たちのJUnitテストを改善するのに使えるたくさんの機能を提供します。
以下の例を見れば、私は例外について3つのことをテストしています。

  1. スローされた例外の種類
  2. 例外メッセージ
  3. 例外の原因


public class MyTest {

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

    ClassUnderTest classUnderTest;

    @Before
    public void setUp() throws Exception {
        classUnderTest = new ClassUnderTest();
    }

    @Test
    public void testAppleisSweetAndRed() throws Exception {

        exceptions.expect(Exception.class);
        exceptions.expectMessage("this is the exception message");
        exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause));

        classUnderTest.methodUnderTest("param1", "param2");
    }

}
5
Jobin Joseph

以下のように、電源を入れたり切ったりできるMatcherを作るだけです。

public class ExceptionMatcher extends BaseMatcher<Throwable> {
    private boolean active = true;
    private Class<? extends Throwable> throwable;

    public ExceptionMatcher(Class<? extends Throwable> throwable) {
        this.throwable = throwable;
    }

    public void on() {
        this.active = true;
    }

    public void off() {
        this.active = false;
    }

    @Override
    public boolean matches(Object object) {
        return active && throwable.isAssignableFrom(object.getClass());
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("not the covered exception type");
    }
}

使用するには:

public ExpectedException exception = ExpectedException.none();を追加してから:

ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();
5
Tor P

例外を返さなければならないメソッドの後にアサーション失敗を使用できます。

try{
   methodThatThrowMyException();
   Assert.fail("MyException is not thrown !");
} catch (final Exception exception) {
   // Verify if the thrown exception is instance of MyException, otherwise throws an assert failure
   assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !");
   // In case of verifying the error message
   MyException myException = (MyException) exception;
   assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage());
}
5
Shessuky

NamShubWriter が言ったことに加えて、次のことを確認してください。

  • ExpectedExceptionインスタンスはpublic関連質問
  • ExpectedExceptionは@Beforeメソッドなどでインスタンス化されません。この post は、JUnitの実行順序の複雑さをすべて明確に説明しています。

notしないでください:

@Rule    
public ExpectedException expectedException;

@Before
public void setup()
{
    expectedException = ExpectedException.none();
}

最後に、 this ブログ投稿では、特定の例外がスローされたことをアサートする方法を明確に示しています。

4
Bruce Wayne

ライブラリassertj-coreを推奨して、junitテストで例外を処理します

Java 8では、次のようになります。

//given

//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));

//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);
3
Piotr R

Java8とJunit4の解決策は、この機能を使用することです。

public Throwable assertThrows(Class<? extends Throwable> expectedException, Java.util.concurrent.Callable<?> funky) {
    try {
        funky.call();
    } catch (Throwable e) {
        if (expectedException.isInstance(e)) {
            return e;
        }
        throw new AssertionError(
                String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e));
    }
    throw new AssertionError(
            String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException));
}

使用法は次のとおりです。

    assertThrows(ValidationException.class,
            () -> finalObject.checkSomething(null));

唯一の制限は、ラムダ式でfinalオブジェクト参照を使用することです。このソリューションは@Test(expected = IndexOutOfBoundsException.class)ソリューションを使ってメソッドレベルでthowableを期待する代わりにテストアサーションを続けることを可能にします。

2
Donatello

例えば、あなたは下記のコードの断片のためにJunitを書きたいと思うでしょう。

public int divideByZeroDemo(int a,int b){

    return a/b;
}

public void exceptionWithMessage(String [] arr){

    throw new ArrayIndexOutOfBoundsException("Array is out of bound");
}

上記のコードは発生する可能性がある未知の例外をテストするためのもので、下のものはカスタムメッセージで例外をアサートするためのものです。

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

private Demo demo;
@Before
public void setup(){

    demo=new Demo();
}
@Test(expected=ArithmeticException.class)
public void testIfItThrowsAnyException() {

    demo.divideByZeroDemo(5, 0);

}

@Test
public void testExceptionWithMessage(){


    exception.expectMessage("Array is out of bound");
    exception.expect(ArrayIndexOutOfBoundsException.class);
    demo.exceptionWithMessage(new String[]{"This","is","a","demo"});
}
1
Shirsh Sinha
    @Test(expectedException=IndexOutOfBoundsException.class) 
    public void  testFooThrowsIndexOutOfBoundsException() throws Exception {
         doThrow(IndexOutOfBoundsException.class).when(foo).doStuff();  
         try {
             foo.doStuff(); 
            } catch (IndexOutOfBoundsException e) {
                       assertEquals(IndexOutOfBoundsException .class, ex.getCause().getClass());
                      throw e;

               }

    }

これは、メソッドが正しい例外をスローしたかどうかをチェックする別の方法です。

0
MangduYogii

テストケースの書き方は2通りあります

  1. メソッドによってスローされる例外でテストに注釈を付けます。このようなもの@Test(expected = IndexOutOfBoundsException.class)
  2. Try catchブロックを使用してテストクラスの例外をキャッチし、テストクラスのメソッドからスローされたメッセージをアサートするだけです。

    try{
    }
    catch(exception to be thrown from method e)
    {
         assertEquals("message", e.getmessage());
    }
    

これであなたの質問に答えられることを願っていますハッピーラーニング...

0
Mohit ladia

Java 8では、チェックするコードと予期される例外をパラメータとして取るメソッドを作成できます。

private void expectException(Runnable r, Class<?> clazz) { 
    try {
      r.run();
      fail("Expected: " + clazz.getSimpleName() + " but not thrown");
    } catch (Exception e) {
      if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e);
    }
  }

そしてあなたのテストの中で:

expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);

利点:

  • どのライブラリにも依存していない
  • ローカライズされたチェック - より正確で、必要に応じて1回のテストでこのような複数のアサーションを持つことができます
  • 使いやすい
0
fahrenx

Java 8のラムダを使った私の解決策:

public static <T extends Throwable> T assertThrows(Class<T> expected, ThrowingRunnable action) throws Throwable {
    try {
        action.run();
        Assert.fail("Did not throw expected " + expected.getSimpleName());
        return null; // never actually
    } catch (Throwable actual) {
        if (!expected.isAssignableFrom(actual.getClass())) { // runtime '!(actual instanceof expected)'
            System.err.println("Threw " + actual.getClass().getSimpleName() 
                               + ", which is not a subtype of expected " 
                               + expected.getSimpleName());
            throw actual; // throw the unexpected Throwable for maximum transparency
        } else {
            return (T) actual; // return the expected Throwable for further examination
        }
    }
}

Runnableは必須のthrowsを宣言していないため、FunctionalInterfaceを定義する必要があります。

@FunctionalInterface
public interface ThrowingRunnable {
    void run() throws Throwable;
}

この方法は次のように使用できます。

class CustomException extends Exception {
    public final String message;
    public CustomException(final String message) { this.message = message;}
}
CustomException e = assertThrows(CustomException.class, () -> {
    throw new CustomException("Lorem Ipsum");
});
assertEquals("Lorem Ipsum", e.message);
0
heio