Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use jUnit 5 Assertions to check, whether exception message starts with a String?

I use org.junit.jupiter.api.Assertions object to assert an exception is thrown:

Assertions.assertThrows(
        InvalidParameterException.class,
        () -> new ThrowingExceptionClass().doSomethingDangerous());

Simplified, the exception thrown has a variable part dateTime in its message:

final String message = String.format("Either request is too old [dateTime=%s]", date);
new InvalidParameterException(message);

As of version I use 5.4.0 the Assertions provide three methods checking the exception is thrown:

  • assertThrows​(Class<T> expectedType, Executable executable)
  • assertThrows​(Class<T> expectedType, Executable executable, String message)
  • assertThrows​(Class<T> expectedType, Executable executable, Supplier<String> messageSupplier)

Neither of them provides a mechanism checking whether a String starts with another String. The last 2 methods only check whether the String is equal. How do I check easily whether the exception message starts with "Either request is too old" since more message variations might occur within the same InvalidParameterException?


I'd appreciate a method assertThrows​(Class<T> expectedType, Executable executable, Predicate<String> messagePredicate) where the predicate would provide the thrown message and the assertion passes when if predicate returns true such as:

Assertions.assertThrows(
    InvalidParameterException.class,
    () -> new ThrowingExceptionClass().doSomethingDangerous()
    message -> message.startsWith("Either request is too old"));

Sadly, it doesn't exist. Any workaround?

like image 587
Nikolas Charalambidis Avatar asked Oct 07 '19 12:10

Nikolas Charalambidis


2 Answers

The assertThrows() method returns an exception instance of the expected type (if any). You can then manually get a message from is and check if it starts with the string you desire.

Here is a sample from doc

@Test
void exceptionTesting() {
    Exception exception = assertThrows(ArithmeticException.class, () ->
        calculator.divide(1, 0));
    assertEquals("/ by zero", exception.getMessage());
}
like image 198
lotor Avatar answered Sep 23 '22 02:09

lotor


You should test the content of the message text of an exception only if that message is a specified part of the API of the unit you are testing. But it is questionable whether you should do that.

The message text of exceptions should not normally be presented to users, as part of the UI of your application.

Specifying the content of the message text encourages clients of the API to parse that message text to learn specific information about the exceptional condition. This is tricky, error prone and unnecessary. In your case, clients might be tempted to parse the message text to extract the date value.

Instead, create a custom exception type that more specifically describes the exceptional condition. In your case, you would want your custom exception class to extend InvalidParameterException. Your custom exception class could have a date field to make the additional data available. You unit test could check that the method under test throws an exception of the correct type, and that it has a date field with the correct value.

like image 22
Raedwald Avatar answered Sep 24 '22 02:09

Raedwald