15

編集:現時点では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の使用を減らす可能性はありませんか?

4

5 に答える 5

33

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());
}
}
于 2010-06-21T08:54:46.433 に答える
13

予期される例外があり、アノテーションを使用してそれをトラップできない場合は、それをキャッチして、期待どおりの結果が得られたことを表明する必要があります。例えば:

Throwable caught = null;
try {
   somethingThatThrows();
} catch (Throwable t) {
   caught = t;
}
assertNotNull(caught);
assertSame(FooException.class, caught.getClass());

代わりに注釈を使用できる場合は、より明確になるため、注釈を使用してください。しかし、それが常に可能であるとは限りません(たとえば、一連のメソッドをテストしているため、またはJUnit 3を使用しているため)。

于 2010-06-21T08:52:42.603 に答える
3

JUnit 4 では、代わりにアノテーションを使用できます。ただし、これを正しく機能させるには、テストを 3 つの異なるメソッドに分ける必要があります。最初のシナリオで例外をキャッチするのは失敗するはずなので、それに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());
}
于 2010-06-21T08:48:14.370 に答える
2

最も簡潔な構文は、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());
}
于 2012-06-22T16:52:14.943 に答える
1

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());
}
于 2017-07-07T02:36:39.467 に答える