編集:現在、JUnit 4は使用できません。
こんにちは、
JUnitを使用した「スマート」な例外テストについて質問があります。現時点では、次のようにしています。
public void testGet() {
SoundFileManager sfm = new SoundFileManager();
// Test adding a sound file and then getting it by id and name.
try {
SoundFile addedFile = sfm.addSoundfile("E:\\Eclipse_Prj\\pSound\\data\\Adrenaline01.wav");
SoundFile sf = sfm.getSoundfile(addedFile.getID());
assertTrue(sf!=null);
System.out.println(sf.toString());
sf = sfm.getSoundfileByName("E:\\Eclipse_Prj\\pSound\\data\\Adrenaline01.wav");
assertTrue(sf!=null);
System.out.println(sf.toString());
} catch (RapsManagerException e) {
System.out.println(e.getMessage());
}
// Test get with invalid id.
try {
sfm.getSoundfile(-100);
fail("Should have raised a RapsManagerException");
} catch (RapsManagerException e) {
System.out.println(e.getMessage());
}
// Test get by name with invalid name
try {
sfm.getSoundfileByName(new String());
fail("Should have raised a RapsManagerException");
} catch (RapsManagerException e) {
System.out.println(e.getMessage());
}
}
ご覧のとおり、例外をスローすることになっている関数ごとに1つのtry/catchブロックが必要です。これを行うには良い方法ではないようです-またはtry/catchの使用を減らす可能性はありませんか?
testGet
を複数の個別のテストに分割する必要があることをお勧めします。個々のtry/catchブロックは、互いにかなり独立しているようです。共通の初期化ロジックを独自のセットアップメソッドに抽出することもできます。
それができたら、次のようなJUnit4の例外アノテーションサポートを使用できます。
public class MyTest {
private SoundManager sfm;
@Before
public void setup() {
sfm = new SoundFileManager();
}
@Test
public void getByIdAndName() {
// Test adding a sound file and then getting it by id and name.
SoundFile addedFile =
sfm.addSoundfile("E:\\Eclipse_Prj\\pSound\\data\\Adrenaline01.wav");
SoundFile sf = sfm.getSoundfile(addedFile.getID());
assertTrue(sf!=null);
System.out.println(sf.toString());
sf = sfm.getSoundfileByName("E:\\Eclipse_Prj\\pSound\\data\\Adrenaline01.wav");
assertTrue(sf!=null);
System.out.println(sf.toString());
}
@Test(expected=RapsManagerException.class)
public void getByInvalidId() {
// Test get with invalid id.
sfm.getSoundfile(-100);
}
@Test(expected=RapsManagerException.class)
public void getByInvalidName() {
// Test get with invalid id.
sfm.getSoundfileByName(new String());
}
}
予期した例外があり、それをトラップするための注釈を使用できない場合は、それをキャッチして、期待どおりの結果を得たことを表明する必要があります。例えば:
Throwable caught = null;
try {
somethingThatThrows();
} catch (Throwable t) {
caught = t;
}
assertNotNull(caught);
assertSame(FooException.class, caught.getClass());
代わりにアノテーションを使用できる場合は、はるかに明確であるため、それを行ってください。しかし、それが常に可能であるとは限りません(たとえば、一連のメソッドをテストしているため、またはJUnit 3を使用しているため)。
JUnit 4では、代わりにアノテーションを使用できます。ただし、これを正しく機能させるには、テストを3つの異なる方法に分ける必要があります。最初のシナリオで例外をキャッチするIMHOは失敗するはずなので、それに応じてcatch
ブロックを変更したことに注意してください。
public void testGet() {
SoundFileManager sfm = new SoundFileManager();
// Test adding a sound file and then getting it by id and name.
try {
SoundFile addedFile = sfm.addSoundfile("E:\\Eclipse_Prj\\pSound\\data\\Adrenaline01.wav");
SoundFile sf = sfm.getSoundfile(addedFile.getID());
assertTrue(sf!=null);
System.out.println(sf.toString());
sf = sfm.getSoundfileByName("E:\\Eclipse_Prj\\pSound\\data\\Adrenaline01.wav");
assertTrue(sf!=null);
System.out.println(sf.toString());
} catch (RapsManagerException e) {
fail(e.getMessage());
}
}
@Test(expected=RapsManagerException.class)
public void testGetWithInvalidId() {
SoundFileManager sfm = new SoundFileManager();
sfm.getSoundfile(-100);
}
@Test(expected=RapsManagerException.class)
public void testGetWithInvalidName() {
SoundFileManager sfm = new SoundFileManager();
sfm.getSoundfileByName(new String());
}
最も簡潔な構文は catch-exception によって提供されます:
public void testGet() {
SoundFileManager sfm = new SoundFileManager();
... // setup sound file manager
verifyException(sfm, RapsManagerException.class)
.getSoundfile(-100);
verifyException(sfm, RapsManagerException.class)
.getSoundfileByName(new String());
}
Java 8では、ラムダ式を使用して、例外がスローされるタイミングをより厳密に制御できます。アノテーションメソッドを使用する場合、テストのどこかで例外がスローされることを表明しているだけです。メソッド。テストで複数行のコードを実行している場合、テストが失敗したときにテストがパスするリスクがあります。Java 8ソリューションはこのようなものです。
static void <T extends Exception> expectException(Class<T> type, Runnable runnable) {
try {
runnable.run()
} catch (Exception ex) {
assertTrue(ex.getClass().equals(type));
return;
}
assertTrue(false);
}
使用法:
@Test
public void test()
MyClass foo = new MyClass();
// other setup code here ....
expectException(MyException.class, () -> foo.bar());
}