首页 文章

JUnit异常测试

提问于
浏览
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());
        }

    }

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

5 回答

  • 1

    我建议您需要将_2474608分解为多个单独的测试 . 各个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());
    }
    }
    
  • 32

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

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

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

  • 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());
    }
    
  • 12

    最简洁的语法由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());
    }
    
  • 2

    在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());
    }
    

相关问题