我想知道当使用 String.format() 生成该消息时,是否有一种干净且完整的方法可以对附加到引发的异常的消息进行断言。例如,像这样的类:
public class Car {
public static final String DRIVE_ERROR = "Can't drive while car %s is parked!";
private String name;
private boolean parked;
public Car(String name) {
this.name = name;
this.parked = true;
}
public void drive() {
if (parked) {
throw new IllegalStateException(String.format(DRIVE_ERROR, name));
}
}
}
(抱歉这个奇怪的例子,只是想让它尽可能简单) 现在,如果我要测试汽车,我会有这样的类(class):
public class CarTest {
@Test
public void drive_test() {
Car car = new Car("Greased Lightning");
assertThatThrownBy(() -> car.drive())
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("???");
}
}
问题是,对消息进行断言的最佳方式是什么?在这个例子中,我可以分离出汽车名称的声明,然后自己使用 String 格式从 Car 中获取静态字符串并格式化名称,但这似乎有很多额外的代码,并且不能是在很多情况下都很容易使用(例如,当格式化字符串中的项目在运行时确定时)。我真正希望能够做的是将错误消息字符串传递给 hasMessageContaining
并让它忽略“%s”占位符并接受该位置的任何内容。有没有办法用assertJ 进行字符串的正则表达式匹配?或者其他一些干净利落的方法?
编辑:我也愿意接受抛出具有更容易测试消息的异常的替代方案。一种解决方案是仅使用字符串连接,例如抛出新的异常(STATIC_ERROR_MESSAGE + name)
,然后测试消息是否包含第一部分,但这确实限制了您的消息格式化能力,并且看起来不太干净.
最佳答案
与常规字符串断言相比,异常消息断言受到限制。
你可以做的是使用 matches
或containsPattern
断言,例如:
@Test
public void test() {
// GIVEN some preconditions
// WHEN
Throwable thrown = catchThrowableOfType(() -> { throw new IllegalStateException("boom!"); },
IllegalStateException.class);
// THEN
assertThat(thrown.getMessage()).matches(".oo.")
.containsPattern("oo.");
// or even better thanks to Rolland Illig suggestion
assertThat(thrown).hasMessageMatching(".oo.");
}
请注意,通过使用catchThrowableOfType
,您不必再检查捕获的异常是否属于预期类型。
关于java - AssertJ:使用 String.format 生成的消息测试异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52819393/