How do I assert my exception message with JUnit Test annotation?

前端 未结 12 2000
广开言路
广开言路 2020-12-12 08:53

I have written a few JUnit tests with @Test annotation. If my test method throws a checked exception and if I want to assert the message along with the exceptio

相关标签:
12条回答
  • 2020-12-12 09:03

    I like user64141's answer but found that it could be more generalized. Here's my take:

    public abstract class ExpectedThrowableAsserter implements Runnable {
    
        private final Class<? extends Throwable> throwableClass;
        private final String expectedExceptionMessage;
    
        protected ExpectedThrowableAsserter(Class<? extends Throwable> throwableClass, String expectedExceptionMessage) {
            this.throwableClass = throwableClass;
            this.expectedExceptionMessage = expectedExceptionMessage;
        }
    
        public final void run() {
            try {
                expectException();
            } catch (Throwable e) {
                assertTrue(String.format("Caught unexpected %s", e.getClass().getSimpleName()), throwableClass.isInstance(e));
                assertEquals(String.format("%s caught, but unexpected message", throwableClass.getSimpleName()), expectedExceptionMessage, e.getMessage());
                return;
            }
            fail(String.format("Expected %s, but no exception was thrown.", throwableClass.getSimpleName()));
        }
    
        protected abstract void expectException();
    
    }
    

    Note that leaving the "fail" statement within the try block causes the related assertion exception to be caught; using return within the catch statement prevents this.

    0 讨论(0)
  • 2020-12-12 09:05

    Actually, the best usage is with try/catch. Why? Because you can control the place where you expect the exception.

    Consider this example:

    @Test (expected = RuntimeException.class)
    public void someTest() {
       // test preparation
       // actual test
    }
    

    What if one day the code is modified and test preparation will throw a RuntimeException? In that case actual test is not even tested and even if it doesn't throw any exception the test will pass.

    That is why it is much better to use try/catch than to rely on the annotation.

    0 讨论(0)
  • 2020-12-12 09:05

    Import the catch-exception library, and use that. It's much cleaner than the ExpectedException rule or a try-catch.

    Example form their docs:

    import static com.googlecode.catchexception.CatchException.*;
    import static com.googlecode.catchexception.apis.CatchExceptionHamcrestMatchers.*;
    
    // given: an empty list
    List myList = new ArrayList();
    
    // when: we try to get the first element of the list
    catchException(myList).get(1);
    
    // then: we expect an IndexOutOfBoundsException with message "Index: 1, Size: 0"
    assertThat(caughtException(),
      allOf(
        instanceOf(IndexOutOfBoundsException.class),
        hasMessage("Index: 1, Size: 0"),
        hasNoCause()
      )
    );
    
    0 讨论(0)
  • 2020-12-12 09:09

    I like the @Rule answer. However, if for some reason you don't want to use rules. There is a third option.

    @Test (expected = RuntimeException.class)
    public void myTestMethod()
    {
       try
       {
          //Run exception throwing operation here
       }
       catch(RuntimeException re)
       {
          String message = "Employee ID is null";
          assertEquals(message, re.getMessage());
          throw re;
        }
        fail("Employee Id Null exception did not throw!");
      }
    
    0 讨论(0)
  • 2020-12-12 09:09

    If using @Rule, the exception set is applied to all the test methods in the Test class.

    0 讨论(0)
  • 2020-12-12 09:16

    Do you have to use @Test(expected=SomeException.class)? When we have to assert the actual message of the exception, this is what we do.

    @Test
    public void myTestMethod()
    {
      try
      {
        final Integer employeeId = null;
        new Employee(employeeId);
        fail("Should have thrown SomeException but did not!");
      }
      catch( final SomeException e )
      {
        final String msg = "Employee ID is null";
        assertEquals(msg, e.getMessage());
      }
    }
    
    0 讨论(0)
提交回复
热议问题