JUnit异常测试

时间:2010-06-21 08:46:13

标签: java unit-testing exception junit junit3

编辑:目前不提供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());
        }

    }

正如您所看到的,我需要为每个应该抛出异常的函数提供一个try / catch块。这似乎不是一个好方法 - 或者是否有可能减少try / catch的使用?

5 个答案:

答案 0 :(得分:32)

我建议您需要将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());
}
}

答案 1 :(得分:12)

如果你有一个预期的异常并且你不能使用注释来捕获它,你需要捕获它并断言你已经得到了你所期望的。例如:

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

如果您可以使用注释,请执行此操作,因为它更清晰。但这并不总是可行的(例如,因为您正在测试一系列方法,或者因为您正在使用JUnit 3)。

答案 2 :(得分: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());
}

答案 3 :(得分: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());
}

答案 4 :(得分:1)

在Java 8中,您可以使用lambda表达式来更严格地控​​制何时抛出异常。如果您使用注释方法,那么您只是断言在测试方法中的某处抛出了异常。如果您在测试中执行了多行代码,那么当测试失败时,您将面临测试通过的风险。 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());
}