In Java how can I validate a thrown exception with JUnit?

前端 未结 10 1186
甜味超标
甜味超标 2020-11-30 05:47

When writing unit tests for a Java API there may be circumstances where you want to perform more detailed validation of an exception. I.e. more than is offered by the @t

相关标签:
10条回答
  • 2020-11-30 06:28

    For JUNIT 3.x

    public void test(){
       boolean thrown = false;
       try{
          mightThrowEx();
       } catch ( Surprise expected ){
          thrown = true;
          assertEquals( "message", expected.getMessage());
       }
      assertTrue(thrown );
    }
    
    0 讨论(0)
  • 2020-11-30 06:30

    For JUnit 5 it is much easier:

        @Test
        void testAppleIsSweetAndRed() throws Exception {
    
            IllegalArgumentException ex = assertThrows(
                    IllegalArgumentException.class,
                    () -> testClass.appleIsSweetAndRed("orange", "red", "sweet"));
    
            assertEquals("this is the exception message", ex.getMessage());
            assertEquals(NullPointerException.class, ex.getCause().getClass());
        }
    

    By returning the exception object itself, assertThrows() allows you to test every aspect regarding your thrown exceptions.

    0 讨论(0)
  • 2020-11-30 06:33

    As provided in your answer, it's a good approach. In addition to this:

    You could wrap the function expectException into a new Annotation, called ExpectedException.
    An annotated method would look like this:

    @Test
    @ExpectedException(class=WrapperException.class, message="Exception Message", causeException)
    public void testAnExceptionWrappingFunction() {
      //whatever you test
    }
    

    This way would be more readable, but it's exactly the same approach.

    Another reason is: I like Annotations :)

    0 讨论(0)
  • 2020-11-30 06:33

    The following helper method (adapted from this blog post) does the trick:

    /**
     * Run a test body expecting an exception of the
     * given class and with the given message.
     *
     * @param test              To be executed and is expected to throw the exception.
     * @param expectedException The type of the expected exception.
     * @param expectedMessage   If not null, should be the message of the expected exception.
     * @param expectedCause     If not null, should be the same as the cause of the received exception.
     */
    public static void expectException(
            Runnable test,
            Class<? extends Throwable> expectedException,
            String expectedMessage,
            Throwable expectedCause) {
        try {
            test.run();
        }
        catch (Exception ex) {
            assertSame(expectedException, ex.getClass());
            if (expectedMessage != null) {
                assertEquals(expectedMessage, ex.getMessage());
            }
    
            if (expectedCause != null) {
                assertSame(expectedCause, ex.getCause());
            }
    
            return;
        }
    
        fail("Didn't find expected exception of type " + expectedException.getName());
    }
    

    The test code can then invoke this as follows:

    TestHelper.expectException(
            new Runnable() {
                public void run() {
                    classInstanceBeingTested.methodThatThrows();
                }
            },
            WrapperException.class,
            "Exception Message",
            causeException
    );
    
    0 讨论(0)
提交回复
热议问题