如何使用 jUnit 5 断言检查异常消息是否以字符串开头?

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

我使用 org.junit.jupiter.api.Assertions 对象断言抛出异常:

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

简化,抛出的异常在其消息中有一个可变部分dateTime

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

从我使用 5.4.0 的版本开始,Assertions 提供了三种检查抛出异常的方法:

它们都没有提供检查字符串 是否以另一个字符串 开头的机制。最后 2 个方法只检查 String 是否相等。我如何轻松检查异常消息是否以 "Either request is too old" 开头,因为在同一 InvalidParameterException?

中可能会出现更多消息变化

我希望有一种方法 assertThrows​(Class<T> expectedType, Executable executable, Predicate<String> messagePredicate),其中谓词将提供抛出的 message 并且断言在 if predicate returns true 时通过,例如:

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

遗憾的是,它不存在。任何解决方法?

assertThrows() 方法 returns 预期类型的​​异常实例(如果有)。然后您可以手动从 is 获取消息并检查它是否以您想要的字符串开头。

这是来自 doc

的示例
@Test
void exceptionTesting() {
    Exception exception = assertThrows(ArithmeticException.class, () ->
        calculator.divide(1, 0));
    assertEquals("/ by zero", exception.getMessage());
}

只有当消息是您正在测试的单元的 API 的指定部分时,您才应该测试异常消息文本的内容。但是你是否应该这样做值得怀疑。

message text of exceptions should not normally be presented to users,作为您申请 UI 的一部分。

指定消息文本的内容会鼓励 API 的客户端解析该消息文本以了解有关异常情况的具体信息。这是棘手的、容易出错的和不必要的。在您的情况下,客户端可能会试图解析消息文本以提取 date 值。

相反,create a custom exception type 更具体地描述了异常情况。在您的情况下,您希望自定义异常 class 扩展 InvalidParameterException。您的自定义例外 class 可以有一个日期字段来使附加数据可用。您的单元测试可以检查被测方法是否抛出正确类型的异常,以及它是否有一个具有正确值的日期字段。