Pat*_*k M 67 java junit unit-testing assertj
我们有一个测试套件,主要使用与Hamcrest匹配器的JUnit断言.我们的一个团队开始尝试使用AssertJ,并以其语法,灵活性和声明性来给人们留下深刻印象.JUnit提供了一个功能,我在AssertJ中找不到相应的功能:添加自定义断言失败消息.
我们经常比较那些不是为了人类可读性而且会有随机看似Ids或UUID的对象,并且不可能通过它们包含的数据来判断它们应该是什么.遗憾的是,对于我们的代码库来说,这是一个不可避免的情况,因为它实现的目的之一是在其他服务之间映射数据,而不必理解它是什么.
在JUnit中,该assertThat方法String reason在Matcher<T>param 之前提供带参数的版本.这样就可以添加一个简短的调试字符串来解决这个问题,就像比较对人类意味着什么一样.
另一方面,AssertJ提供了许多不同的泛化static assertThat方法,这些方法返回某种形式的接口Assert或其中许多实现类之一.此接口不提供设置要包含在故障中的自定义消息的标准方法.
有没有办法从AssertJ API或其扩展之一获得此功能,而无需为我们要添加消息的每个断言类型创建自定义断言类?
Pat*_*k M 116
以经典的方式,我在发布问题后找到了我想要的东西.希望这将使下一个人更容易找到,而不必首先知道它的名称.神奇的方法是看似简短的命名as,它是另一个AbstractAssert实现的接口的一部分:Descriptable,而不是基本的Assert接口.
public S as(String description, Object... args)设置此对象的描述支持
String.format(String, Object...)语法.
示例:Run Code Online (Sandbox Code Playgroud)try { // set a bad age to Mr Frodo which is really 33 years old. frodo.setAge(50); // you can specify a test description with as() method or describedAs(), it supports String format args assertThat(frodo.getAge()).as("check %s's age", frodo.getName()).isEqualTo(33); } catch (AssertionError e) { assertThat(e).hasMessage("[check Frodo's age] expected:<[33]> but was:<[50]>"); }
hasMessage如果断言失败,catch块中的引用字符串将出现在单元测试输出日志中.
我通过注意问题中链接failWithMessage的自定义断言页面中的帮助程序找到了这个.该方法的JavaDoc指出它受到保护,因此调用者无法使用它来设置自定义消息.但它确实提到了as帮手:
此外,此方法
as(String, Object...)遵循用户定义的任何描述设置或覆盖的错误消息overridingErrorMessage(String, Object...).
......而overridingErrorMessage帮手,它完全取代了标准AssertJ expected: ... but was:...所提供的新的字符串消息.
AssertJ主页在功能高亮页面之前没有提到任何助手,它显示as了软断言部分中助手的示例,但没有直接描述它的作用.
sle*_*ske 11
要为Patrick M的答案添加另一个选项:
除了使用Descriptable.as,您还可以使用AbstractAssert.withFailMessage():
try {
// set a bad age to Mr Frodo which is really 33 years old.
frodo.setAge(50);
// you can specify a test description via withFailMessage(), supports String format args
assertThat(frodo.getAge()).
withFailMessage("Frodo's age is wrong: %s years, difference %s years",
frodo.getAge(), frodo.getAge()-33).
isEqualTo(33);
} catch (AssertionError e) {
assertThat(e).hasMessage("Frodo's age is wrong: 50 years, difference 17 years");
}
Run Code Online (Sandbox Code Playgroud)
使用的区别Descriptable.as在于,它使您可以完全控制自定义消息 -没有“预期”和“但是”。
如果要测试的实际值对表示不有用,这将很有用-此方法使您可以显示其他可能计算出的值,或者根本不显示。
请注意,就像一样Descriptable.as,您必须withFailMessage() 在任何实际的断言之前调用-否则它将不起作用,因为该断言将首先触发。Javadoc中对此进行了说明。
Abh*_*kar 11
到目前为止提到的两个选项是as和withFailMessage,所以我不会再讨论语法或用法。要了解它们之间的差异以及它们的用途,请考虑我们测试导出指标的用例:
// map of all metrics, keyed by metrics name
Map<String, Double> invocations = ...
List.of(
"grpc.client.requests.sent",
"grpc.client.responses.received",
"grpc.server.requests.received",
"grpc.server.responses.sent"
).forEach { counter ->
var meter = // create meter name using counter
assertThat(invocations)
.withFailMessage("Meter %s is not found", meter)
.containsKey(meter)
assertThat(invocations.get(meter))
.as(meter)
.isEqualTo(0.0)
}
Run Code Online (Sandbox Code Playgroud)
我使用 Java 11 语法来减少一些样板文件。
如果没有withFailMessage,如果映射中不存在仪表,则默认输出包含映射中所有条目的转储,这会扰乱测试日志。我们不在乎存在什么其他仪表,只关心我们想要的仪表在那里。
使用withFailMessage,输出变为:
java.lang.AssertionError: Meter blah is not found
Run Code Online (Sandbox Code Playgroud)
至于as,它仅将给定的消息附加到输出中,但保留失败的比较,这非常有用。我们得到:
org.opentest4j.AssertionFailedError: [blah]
Expecting:
<1.0>
to be equal to:
<0.0>
but was not.
Run Code Online (Sandbox Code Playgroud)
小智 7
使用 AssertJ 中的内置as()方法。例如:
assertThat(myTest).as("The test microservice is not active").isEqualTo("active");
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20527 次 |
| 最近记录: |