AssertJ:使用 String.format 生成的消息测试异常
AssertJ: Testing exceptions with messages generated with String.format
我想知道当使用 String.format() 生成该消息时,是否有一种干净而完整的方法来断言附加到抛出异常的消息。例如,class 如:
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("???");
}
}
问题是,对消息进行断言的最佳方式是什么?在这个例子中,我可以分离出汽车名称的声明,然后自己使用字符串格式从 Car 中获取静态字符串并在名称中进行格式化,但这似乎有很多额外的代码,并且不能在很多情况下很容易使用(例如,当格式化字符串中的项目在运行时确定时)。我真正想做的是将错误消息字符串传递给 hasMessageContaining
并让它忽略“%s”占位符并接受该位置的任何内容。有没有办法用 assertJ 进行字符串的正则表达式匹配?或者其他一些干净的方法?
编辑:我也对抛出具有更易于测试的消息的异常的替代方案持开放态度。一种解决方案是仅使用字符串连接,例如 throw new Exception(STATIC_ERROR_MESSAGE + name)
,然后测试消息是否包含第一部分,但这确实限制了您的消息格式化能力并且看起来不太干净。
与常规字符串断言相比,异常消息断言是有限的。
你可以做的是使用 matches
or 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
,您不必再检查捕获的异常是否属于预期类型。
我想知道当使用 String.format() 生成该消息时,是否有一种干净而完整的方法来断言附加到抛出异常的消息。例如,class 如:
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("???");
}
}
问题是,对消息进行断言的最佳方式是什么?在这个例子中,我可以分离出汽车名称的声明,然后自己使用字符串格式从 Car 中获取静态字符串并在名称中进行格式化,但这似乎有很多额外的代码,并且不能在很多情况下很容易使用(例如,当格式化字符串中的项目在运行时确定时)。我真正想做的是将错误消息字符串传递给 hasMessageContaining
并让它忽略“%s”占位符并接受该位置的任何内容。有没有办法用 assertJ 进行字符串的正则表达式匹配?或者其他一些干净的方法?
编辑:我也对抛出具有更易于测试的消息的异常的替代方案持开放态度。一种解决方案是仅使用字符串连接,例如 throw new Exception(STATIC_ERROR_MESSAGE + name)
,然后测试消息是否包含第一部分,但这确实限制了您的消息格式化能力并且看起来不太干净。
与常规字符串断言相比,异常消息断言是有限的。
你可以做的是使用 matches
or 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
,您不必再检查捕获的异常是否属于预期类型。