您可以向AssertJ assertThat添加自定义消息吗?


90

我们有一个测试套件,主要使用带有Hamcrest匹配器的JUnit断言。我们的一个团队开始对AssertJ进行实验,并以其语法,灵活性和声明性给人留下了深刻的印象。JUnit提供的一项功能是我无法在AssertJ中找到与之等效的功能:添加自定义断言失败消息。

我们经常在比较不是为了人类可读性而制成的对象,这些对象将具有随机寻找的Id或UUID,并且无法通过包含的数据来判断它们应该是什么。不幸的是,对于我们的代码库来说,这是不可避免的情况,因为它实现的目的之一就是在其他服务之间映射数据而不必了解它是什么。

在JUnit中,该assertThat方法在String reason参数之前提供一个带有参数的版本Matcher<T>。这使得添加简短的调试字符串变得轻而易举,从而避免了对该问题的一些了解,例如,比较对人类意味着什么。

另一方面,AssertJ提供了十亿种不同的通用static assertThat方法,这些方法返回某种形式的接口Assert或其许多实现类之一。此接口不提供设置失败时包括的自定义消息的标准方法。

有什么方法可以从AssertJ API或其扩展之一中获得此功能,而不必为要向其添加消息的每个断言类型创建自定义断言类

Answers:


137

以经典的方式,发布问题后,我发现了自己想要的片刻。希望这将使下一个人更容易找到,而无需首先知道它的名字。魔术方法是具有欺骗性的简称as,它是另一个AbstractAssert实现以下功能的接口的一部分:Descriptable,而不是基本的Assert接口。

public S as(String description, Object... args)

设置此对象支持String.format(String, Object...)语法的描述。
范例:

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帮手,它完全取代了标准AssertJexpected: ... but was:...所提供的新的字符串消息。

在功能突出显示页面之前,AssertJ主页没有提到任何一个帮助程序,该页面as在“软断言”部分中显示了该帮助程序的示例,但没有直接描述它的功能。


22

要为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");
}

使用的区别Descriptable.as在于,它使您可以完全控制自定义消息-没有“预期”和“但是”。

如果要测试的实际值不能用于表示,这很有用-此方法使您可以显示其他可能计算出的值,或者根本不显示。


请注意,就像一样Descriptable.as,您必须withFailMessage() 任何实际的断言之前调用-否则它将不起作用,因为该断言将首先触发。Javadoc中对此进行了说明。


3
“您必须在调用任何实际断言之前先调用withFailMessage()”,这让我很困惑。呼叫withFailMessage事项的顺序;我喜欢AssertJ,但这很糟糕。
Abhijit Sarkar,


0

使用as()AssertJ中的内置方法。例如:

 assertThat(myTest).as("The test microservice is not active").isEqualTo("active");
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.