JUnit Exception Testing

前端 未结 5 525
广开言路
广开言路 2020-12-14 19:54

Edit: Not JUnit 4 available at this time.

Hi there,

I have a question about \"smart\" exception testing with JUnit. At this time, I do it like this:

相关标签:
5条回答
  • 2020-12-14 20:14

    I suggest that you need to break up testGet into multiple separate tests. The individual try/catch blocks seem to be pretty independent of each other. You may also want to extract the common initialization logic into its own setup method.

    Once you have that, you can use JUnit4's exception annotation support, something like this:

    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());
    }
    }
    
    0 讨论(0)
  • 2020-12-14 20:17

    The most concise syntax is provided by 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());
    }
    
    0 讨论(0)
  • 2020-12-14 20:21

    With JUnit 4, you can use annotations instead. However, you should separate your test into 3 distinct methods for this to work cleanly. Note that IMHO catching an exception in the first scenario should be a failure, so I modified the catch block accordingly.

    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());
    }
    
    0 讨论(0)
  • 2020-12-14 20:22

    If you have an expected exception and you can't use an annotation to trap it, you need to catch it and assert that you've got what you expected. For example:

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

    If you can use an annotation instead, do that as it's much clearer. But that's not always possible (e.g., because you're testing a sequence of methods or because you're using JUnit 3).

    0 讨论(0)
  • 2020-12-14 20:33

    In Java 8, you can use lambda expressions to get tighter control over when the exception is thrown. If you use the annotations method then you're only asserting that the exception is thrown somewhere in the test method. If you're executing more than one line of code in the test then you risk your test passing when it should fail. Java 8 solution is something like this.

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

    Usage:

    @Test
    public void test() 
        MyClass foo = new MyClass();
        // other setup code here ....
        expectException(MyException.class, () -> foo.bar());
    }
    
    0 讨论(0)
提交回复
热议问题