JUnit4を慣用的に使用して一部のコードで例外がスローされることをテストする方法を教えてください。
私は確かにこのようなことをすることができますが:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
私は、アノテーションやAssert.xyzあるいは なにか があることを思い出してください。これらは、このような状況では、あまり意味がなく、JUnitの精神をはるかに超えています。
JUnit 4はこれをサポートしています。
@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
編集 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()
よりはるかに優れています。
詳細は この記事 を参照してください。
テストでは method がその例外を投げたことを表明しているだけであり、 特定のコード行 は表明していないことを表明しているので、予想される例外の使用に注意してください。
このようなメソッドは通常非常に単純ですが、より複雑なテストの方が適している可能性があるため、パラメーターの検証をテストするためにこれを使用する傾向があります。
try {
methodThatShouldThrow();
fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}
判断を下す。
前に答えたように、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
開示:私はブログとプロジェクトの著者です。
ちなみに、例外をテストする方法は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());
}
そう
詳細については、 このドキュメント および junit5のユーザーガイド を参照してください。
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ツールにはいくつかの落とし穴があります。
try
-catch
ブロックは、テストされた動作の周りにブロックを記述し、catchブロックにアサーションを記述する必要があります。これは問題ないかもしれませんが、多くの場合、このスタイルはテストの読み取りフローを中断します。また、try
ブロックの最後にAssert.fail
を記述する必要があります。そうしないと、テストがアサーションの片側を見逃す可能性があります。 PMD、findbugsまたはSonarはそのような問題を発見します。
@Test(expected = ...)
機能は、より少ないコードを記述でき、このテストを記述することでコーディングエラーが発生する可能性が低いため、興味深いものです。 しかしこのアプローチにはいくつかの領域が欠けています。
また、メソッドに期待が置かれているため、テストされたコードの記述方法に応じて、テストコードの間違った部分が例外をスローし、誤検知テストにつながる可能性がありますPMD、findbugsまたは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
}
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を使用するとエラーが発生しやすくなります。その場合、ルールの順序が重要だからです。
したがって、上記のオプションにはすべての注意事項があり、明らかにコーダーエラーの影響を受けません。
この回答を作成した後に気付いたプロジェクトは有望に見えます。 catch-exception です。
プロジェクトの説明にあるように、例外をキャッチする流exceptionなコード行をコーダーに記述させ、この例外を後のアサーションに提供します。また、 Hamcrest や AssertJ などのアサーションライブラリを使用できます。
ホームページから取られた迅速な例:
// 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の使用を好むかもしれません。
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");
}
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
ブロックに依存する必要があります。
この回答は 別の質問 からコピーされ、同じ可視性はありません。私は同じ著者です。
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!");
}
}
他の回答のアプローチに対する利点は次のとおりです。
throws
句に記載する必要はありません。JUnit 4.13では、同様のメソッドがorg.junit Assert
に追加されます。
これはどうですか:非常に一般的な例外をキャッチし、それがcatchブロックの外に出ていることを確認してから、例外のクラスが想定どおりであることをアサートします。このアサートは、a)例外のタイプが間違っている場合(例えば、代わりにNull Pointerを受け取った場合)、およびb)例外がこれまでにスローされていない場合に失敗します。
public void testFooThrowsIndexOutOfBoundsException() {
Throwable e = null;
try {
foo.doStuff();
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof IndexOutOfBoundsException);
}
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");
同じ問題を解決するために、私は小さなプロジェクトを立ち上げました: http://code.google.com/p/catch-exception/ /
この小さなヘルパーを使って書く
verifyException(foo, IndexOutOfBoundsException.class).doStuff();
これは、JUnit 4.7のExpectedExceptionルールよりも詳細ではありません。 skaffmanが提供するソリューションと比較して、どのコード行で例外を予想するかを指定できます。これが助けになれば幸いです。
更新: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");
}
try
catch
を使う
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ルール をご覧ください。
またこれをすることができます:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
assert false;
} catch (IndexOutOfBoundsException e) {
assert true;
}
}
私見、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");
が望ましいかもしれません。
@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 にあります。
私はここで多くの方法を試しましたが、それらは複雑だったか、私の要求を完全には満たしていませんでした。実際、ヘルパーメソッドは非常に簡単に書くことができます。
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();
}
});
依存関係がない:モッキートが不要、パワーモックが不要そしてファイナルクラスでうまく動作します。
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("");
}
}
あなたが解決策をご希望の場合:
これが私が書いた効用関数です。
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!" );
}
JUnitは "expected"属性を使ってこれをサポートしています
私の場合は、常に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));
}
JUnit 4以降では、次のようにして例外をテストできます。
@Rule
public ExpectedException exceptions = ExpectedException.none();
これは私たちのJUnitテストを改善するのに使えるたくさんの機能を提供します。
以下の例を見れば、私は例外について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");
}
}
以下のように、電源を入れたり切ったりできる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();
例外を返さなければならないメソッドの後にアサーション失敗を使用できます。
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());
}
NamShubWriter が言ったことに加えて、次のことを確認してください。
notしないでください:
@Rule
public ExpectedException expectedException;
@Before
public void setup()
{
expectedException = ExpectedException.none();
}
最後に、 this ブログ投稿では、特定の例外がスローされたことをアサートする方法を明確に示しています。
ライブラリ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(".......);
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を期待する代わりにテストアサーションを続けることを可能にします。
例えば、あなたは下記のコードの断片のために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"});
}
@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;
}
}
これは、メソッドが正しい例外をスローしたかどうかをチェックする別の方法です。
テストケースの書き方は2通りあります
@Test(expected = IndexOutOfBoundsException.class)
Try catchブロックを使用してテストクラスの例外をキャッチし、テストクラスのメソッドからスローされたメッセージをアサートするだけです。
try{
}
catch(exception to be thrown from method e)
{
assertEquals("message", e.getmessage());
}
これであなたの質問に答えられることを願っていますハッピーラーニング...
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);
利点:
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);