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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28994316/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:10:00  来源:igfitidea点击:

Can you add a custom message to AssertJ assertThat?

javaunit-testingjunitassertj

提问by Patrick M

We have a test suite that primarily uses JUnit assertions with Hamcrest matchers. One of our team started experimenting with AssertJand impressed people with its syntax, flexibility and declarative-ness. There is one feature that JUnit provides that I can't find an equivalent for in AssertJ: adding a custom assert failure message.

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

We're often comparing objects that are not made for human readability and will have random-seeming Ids or UUIDs and it's impossible to tell what they're supposed to be by the data they contain. This is an unavoidable situation for our codebase, sadly, as part of the purpose it fulfills is mapping data between other services without necessarily understanding what it is.

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

In JUnit, the assertThatmethod provides a version with a String reasonparameter before the Matcher<T>param. This makes it trivial to add a short debug string shedding some light on the problem, like what the comparison should mean to a human.

在 JUnit 中,该assertThat方法提供了一个String reasonMatcher<T>param之前带有参数的版本。这使得添加一个简短的调试字符串来阐明问题变得微不足道,比如比较对人类意味着什么。

AssertJ, on the other hand, provides a jillion different genericized static assertThatmethods which return some form of interface Assertor one of its many implementing classes. This interface does not provide a standard way of setting a custom message to be included with failures.

另一方面,AssertJ 提供了无数不同的泛化static assertThat方法,这些方法返回某种形式的接口 Assert或其许多实现类中的一个。此接口不提供设置要包含在故障中的自定义消息的标准方法。

Is there any way to get this functionality from the AssertJ API or one of its extensions without having to create a custom assert class for every assert typewe want to add messages to?

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

采纳答案by Patrick M

And in classic fashion, I found what I was looking for moments after posting the question. Hopefully this will make it easier for the next person to find without first having to know what it's called. The magic method is the deceptively short-named as, which is part of another interface that AbstractAssertimplements: Descriptable, not the base Assert interface.

以经典的方式,我在发布问题后找到了我正在寻找的东西。希望这会让下一个人更容易找到,而不必先知道它叫什么。神奇的方法是看似简短的as,它是另一个AbstractAssert实现:Descriptable 的接口的一部分,而不是基本的 Assert 接口。

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

Sets the description of this object supporting String.format(String, Object...)syntax.
Example :

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

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

Where that quoted string in the catch block hasMessageis what appears in your unit test output log if the assertion fails.

hasMessage如果断言失败,catch 块中引用的字符串将出现在单元测试输出日志中。



I found this by noticing the failWithMessagehelper in the custom assert pagelinked in the question. The JavaDocfor that method points out that it is protected, so it can't be used by callers to set a custom message. It does however mention the ashelper:

我通过注意到问题中链接failWithMessage自定义断言页面中的帮助程序发现了这一点。该方法的JavaDoc指出它是受保护的,因此调用者不能使用它来设置自定义消息。然而,它确实提到了as助手:

Moreover, this method honors any description set with as(String, Object...)or overridden error message defined by the user with overridingErrorMessage(String, Object...).

此外,此方法as(String, Object...)遵循用户定义的任何描述集或覆盖的错误消息overridingErrorMessage(String, Object...)

... and the overridingErrorMessagehelper, which completely replaces the standard AssertJ expected: ... but was:...message with the new string provided.

......而overridingErrorMessage帮手,它完全取代了标准AssertJexpected: ... but was:...所提供的新的字符串消息。

The AssertJ homepage doesn't mention either helper until the features highlights page, which shows examples of the ashelper in the Soft Assertionssection, but doesn't directly describe what it does.

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

回答by Joel Costigliola

FYI this is documented in the new AssertJ website (which is still under construction but already has useful information), see https://assertj.github.io/doc/#assertj-core-assertion-description.

仅供参考,这在新的 AssertJ 网站(仍在建设中但已经有有用的信息)中记录,请参阅https://assertj.github.io/doc/#assertj-core-assertion-description

回答by sleske

To add another option to Patrick M's answer:

在 Patrick M 的回答中添加另一个选项:

Instead of using Descriptable.as, you can also use AbstractAssert.withFailMessage():

除了使用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");
}

The difference to using Descriptable.asis that it gives you complete control over the custom message- there is no "expected" and "but was".

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

This is useful where the actual values being tested are not useful for presentation - this method allows you to show other, possibly calculated values instead, or none at all.

当被测试的实际值对演示没有用时,这很有用 - 此方法允许您显示其他可能计算的值,或者根本不显示。



Do note that, just like Descriptable.as, you must call withFailMessage()beforeany actual assertions - otherwise it will not work, as the assertion will fire first. This is noted in the Javadoc.

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