如何使用 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
提供了三种检查抛出异常的方法:
assertThrows(Class<T> expectedType, Executable executable)
assertThrows(Class<T> expectedType, Executable executable, String message)
assertThrows(Class<T> expectedType, Executable executable, Supplier<String> messageSupplier)
它们都没有提供检查字符串 是否以另一个字符串 开头的机制。最后 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 可以有一个日期字段来使附加数据可用。您的单元测试可以检查被测方法是否抛出正确类型的异常,以及它是否有一个具有正确值的日期字段。
我使用 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
提供了三种检查抛出异常的方法:
assertThrows(Class<T> expectedType, Executable executable)
assertThrows(Class<T> expectedType, Executable executable, String message)
assertThrows(Class<T> expectedType, Executable executable, Supplier<String> messageSupplier)
它们都没有提供检查字符串 是否以另一个字符串 开头的机制。最后 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 可以有一个日期字段来使附加数据可用。您的单元测试可以检查被测方法是否抛出正确类型的异常,以及它是否有一个具有正确值的日期字段。