JUnitテストで特定の例外が投げられることをアサートする方法
JUnitテストにおいて、特定の例外が投げられることを検証する方法について説明します。主に3つの方法があります。
方法1: @Test(expected = ExceptionType.class)
アノテーション
最も単純な方法ですが、例外の型のみを検証できます。
@Test(expected = ArithmeticException.class)
public void testDivisionByZero() {
int result = 10 / 0;
}
@Test
アノテーションにexpected
属性を指定します。- 指定した例外型が投げられなければテスト失敗となります。
- 例外メッセージや原因などを検証することはできません。
方法2: ExpectedException
ルール
例外に関する詳細なアサーションを行うことができます。
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testDivisionByZero() {
thrown.expect(ArithmeticException.class);
thrown.expectMessage("by zero");
thrown.expectCause(is(null));
int result = 10 / 0;
}
@Rule
アノテーションを使用してExpectedException
ルールを導入します。expect
メソッドで期待する例外型を指定します。expectMessage
メソッドで期待する例外メッセージを指定します。
方法3: try-catch
ブロックと手動アサーション
柔軟性がありますが、冗長になりがちです。
@Test
public void testDivisionByZero() {
try {
int result = 10 / 0;
fail("ArithmeticException expected");
} catch (ArithmeticException e) {
// 例外に関するアサーションを行う
assertEquals("by zero", e.getMessage());
}
}
try-catch
ブロックを使用して例外をキャッチします。- 例外が投げられなかった場合、
fail
メソッドを呼び出します。 catch
ブロック内で例外に関するアサーションを行います。
どの方法を選ぶべきか
- 単純に例外の型のみを検証したい場合: 方法1
- 例外に関する詳細なアサーションが必要な場合: 方法2
- 特殊なケースやカスタムアサーションが必要な場合: 方法3
一般的には方法2が推奨されます。
注意:
- JUnitのバージョンによっては、使用可能なアサーション方法が異なる場合があります。
- 例外を適切に処理することは重要であり、テストケースも例外処理を考慮する必要があります。
- JUnitのドキュメント
- Stack Overflow: JUnit right way of test expected exceptions
- CodeJava: JUnit Test Exception Examples
JUnitテストにおける例外テストのコード例
例外の型のみを検証します。
import org.junit.Test;
public class ExceptionTest1 {
@Test(expected = ArithmeticException.class)
public void testDivisionByZero() {
int result = 10 / 0;
}
}
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class ExceptionTest2 {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testDivisionByZero() {
thrown.expect(ArithmeticException.class);
thrown.expectMessage("by zero");
int result = 10 / 0;
}
}
import org.junit.Test;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertEquals;
public class ExceptionTest3 {
@Test
public void testDivisionByZero() {
try {
int result = 10 / 0;
fail("ArithmeticException expected");
} catch (ArithmeticException e) {
assertEquals("by zero", e.getMessage());
}
}
}
JUnit5での例外テスト
JUnit5では assertThrows
メソッドを使用します。
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
public class ExceptionTest 4 {
@Test
public void testDivisionByZero() {
assertThrows(ArithmeticException.class, () -> 10 / 0);
}
}
assertThrows
メソッドの第一引数に期待する例外のクラス、第二引数にテスト対象のコードを渡します。
備考
- JUnitのバージョンによって使用可能な方法が異なります。
- 方法2と方法3はより柔軟な例外テストが可能ですが、コードが冗長になる可能性があります。
- JUnit5の
assertThrows
メソッドは簡潔で読みやすいコードを書くことができます。
TestNG
JUnitと同様に広く使用されているテストフレームワークです。例外テストに関しては、JUnitと似たような方法で対応できます。
import org.testng.annotations.Test;
import org.testng.annotations.ExpectedExceptions;
public class TestNGExceptionTest {
@Test(expectedExceptions = ArithmeticException.class)
public void testDivisionByZero() {
int result = 10 / 0;
}
}
Mockito
モックフレームワークですが、例外を検証する機能も提供しています。
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.mockito.Mockito;
public class MockitoExceptionTest {
@Test
public void testException() {
MyClass mock = Mockito.mock(MyClass.class);
when(mock.method()).thenThrow(new RuntimeException());
try {
mock.method();
fail("Expected RuntimeException");
} catch (RuntimeException e) {
// 例外に関するアサーション
}
}
}
カスタムアサーション
独自の例外検証ロジックを実装することも可能です。
import static org.junit.Assert.fail;
public class CustomAssertion {
public static void assertThrows(Class<? extends Throwable> expected, Runnable runnable) {
try {
runnable.run();
fail("Expected exception: " + expected.getName());
} catch (Throwable t) {
if (!expected.isAssignableFrom(t.getClass())) {
fail("Unexpected exception: " + t.getClass().getName());
}
}
}
}
- JUnitはJavaのユニットテストで最も広く使用されているフレームワークであり、多くのプロジェクトで採用されています。
- TestNGはJUnitと似た機能を提供しますが、一部の機能や使い方が異なる場合があります。
- Mockitoは主にモックオブジェクトの作成に使用されますが、例外検証にも利用できます。
- カスタムアサーションは柔軟性がありますが、実装に手間がかかります。
これらの方法を比較して、プロジェクトの要件やチームの慣習に合わせて適切な方法を選択してください。
- 上記のコード例は簡略化されており、実際のプロジェクトではより詳細な例外検証が必要になる場合があります。
- 例外テストはコードの信頼性を向上させるために重要であり、適切なテストケースを作成することが重要です。
java exception junit