Java 方法是什么;hasOnlyElementsOfType“;在Assertj 3.16.1中已弃用

Java 方法是什么;hasOnlyElementsOfType“;在Assertj 3.16.1中已弃用,java,java-8,junit5,spring-test,assertj,Java,Java 8,Junit5,Spring Test,Assertj,在更新到Assertj 3.16.1后,我发现这段代码不再有效 Throwable thrown = catchThrowable(() -> myObject.methodThrowsException()); assertThat(thrown).isInstanceOf(MyCustomException.class).extracting("fault").hasOnlyElementsOfType(CustomException.class).extracting("code")

在更新到Assertj 3.16.1后,我发现这段代码不再有效

Throwable thrown = catchThrowable(() -> myObject.methodThrowsException());
assertThat(thrown).isInstanceOf(MyCustomException.class).extracting("fault").hasOnlyElementsOfType(CustomException.class).extracting("code").containsExactly("AnotherCustomException");
我收到以下错误消息:

java:cannot find symbol
symbol: method hasOnlyElementsOfType(java.lang.Class<CustomException.class>)
location: class org.assertj.core.api.AbstractObjectAssert<capture#1 of?, capture#2 of ?>
java:找不到符号
符号:方法hasOnlyElementsOfType(java.lang.Class)
位置:class org.assertj.core.api.AbstractObjectAssert
它要么已被弃用,要么现在实现方式不同。我已经查阅了文档并搜索了近两天,看看是否有关于如何使用它的信息,而不是以前如何使用它来实现简单的转换,但还没有找到任何信息。实际上,当我使用这个
包含
的元素来代替给出问题的元素时,我会遇到类似的错误。除了这些方法,还有其他方法可以达到同样的效果吗


任何帮助都将不胜感激

看起来您是从AssertJ 3.12或更早版本升级的

错误在于
AbstractObjectAssert
类没有
hasOnlyElementsOfType
方法。此外,它从未使用过该方法,因此该方法并没有被弃用和删除。相反,这段代码必须是有效的,因为在其他类上调用了
hasonlylementsofType

AssertJ中的大多数内容似乎都经过了
AbstractObjectAssert
。查看AssertJ 3.12中的
AbstractObjectAssert
,我看到它有一个方法
提取(字符串…
——一个varargs方法——返回
AbstractListAssert
。这个类又有一个继承自
abstractiterableasert
hasonyelementsofType
方法。代码
提取(“fault”)
最终是一个varargs调用。这反过来会返回
AbstractListAssert
,因此对
hasOnlyElementsOfType
的后续调用会起作用

然而,在AssertJ 3.13中,
AbstractObjectAssert
有一个新方法
提取(字符串)
——而不是varargs调用。该方法返回
AbstractObjectAssert
,正如我们所看到的,它没有
hasOnlyElementsOfType
方法。根据此版本的AssertJ(或更高版本)编译时,代码
提取(“故障”)
解析为一个arg重载。这将返回
AbstractObjectAssert
,它没有
hasOnlyElementsOfType
方法,因此会出现错误

为了解决这个问题,您可以强制调用
extracting
来调用varargs重载,而不是一个arg重载。varargs调用只是在该位置传递数组的一些语法,因此您可以将代码更改为如下内容:

....extracting(new String[] { "fault" })....
这最终会调用varargs重载,它返回
AbstractListAssert
,其中包含您下一步要调用的
hasonlylementsofType
方法,因此即使在最新的AssertJ版本中也应该可以使用


另外,这是一个相当罕见的例子,添加方法会导致不兼容。通常,添加方法不会影响任何现有代码。但是,向现有API添加新的重载(如AssertJ在3.13中所做的那样)可能会影响现有源代码的重载解析。也就是说,针对旧版本编译的现有源代码最终将调用某些方法。当针对新版本编译相同的源代码时,它可能会在新API中调用不同的方法。如果新方法有不同的行为,它可能会导致微妙的错误。在本例中,新方法具有不同的返回类型,因此预期旧返回类型的代码不再工作。这正是这里发生的事情。

斯图尔特·马克斯(Stuart Marks)在事物的纯AssertJ方面发布了一个伟大的分析,没有什么可添加的。
提取(字符串)
只提取一个值,这意味着你只能链接对象断言,而不是列表断言(提取单个值是有意义的)

我相信你可以做以下断言:

assertThat(抛出).isInstanceOf(MyCustomException.class)
.提取(“错误”)
.isInstanceOf(CustomException.class)
.提取(“代码”)
.isEqualTo(“另一个客户例外”);

感谢Stuart的详细分析!突破性的变化记录在