Assertj 3.16.1 中是否弃用了方法“hasOnlyElementsOfType”

Sam*_*y65 2 java spring-test java-8 assertj junit5

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

Throwable thrown = catchThrowable(() -> myObject.methodThrowsException());
assertThat(thrown).isInstanceOf(MyCustomException.class).extracting("fault").hasOnlyElementsOfType(CustomException.class).extracting("code").containsExactly("AnotherCustomException");
Run Code Online (Sandbox Code Playgroud)

我收到此错误消息:

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 ?>
Run Code Online (Sandbox Code Playgroud)

它要么已被弃用,要么现在以不同的方式实施。我已经浏览了文档并搜索了近两天,看看是否有任何关于如何使用它的信息,而不是以前如何使用它来实现轻松转换,但还没有找到任何东西。当我用它containsOnlyOnceElementsOf代替给出问题的那个时,我实际上得到了一个类似的错误。这些方法是否有其他替代方法可以实现相同的目的?

任何帮助将不胜感激!!!

Stu*_*rks 5

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

错误是AbstractObjectAssert该类没有hasOnlyElementsOfType方法。此外,它从未有过该方法,因此该方法不会被弃用和删除。相反,这段代码肯定有效,因为hasOnlyElementsOfType它是在其他类上调用的。

AssertJ 中的大多数事情似乎都通过AbstractObjectAssert. 看着AbstractObjectAssert在AssertJ 3.12,我看到它有一个方法extracting(String...)-一个可变参数的方法-即返回AbstractListAssert。此类又具有hasOnlyElementsOfTypeAbstractIterableAssert. 代码extracting("fault")最终是一个可变参数调用。这反过来又返回AbstractListAssert,因此随后的工作调用hasOnlyElementsOfType

但是,在 AssertJ 3.13 中,AbstractObjectAssert有一个新方法extracting(String)——不是varargs 调用。AbstractObjectAssert正如我们所见,该方法返回没有该hasOnlyElementsOfType方法。当针对此版本的 AssertJ(或更高版本)编译时,代码extracting("fault")解析为单参数重载。这将返回AbstractObjectAssert它确实具备的hasOnlyElementsOfType方法,因此错误。

要解决此问题,您可以强制调用extracting来调用可变参数重载而不是单参数重载。varargs 调用只是在该位置传递数组的一些语法,因此您可以将代码更改为如下所示:

....extracting(new String[] { "fault" })....
Run Code Online (Sandbox Code Playgroud)

这最终会调用 varargs 重载,它返回AbstractListAssert,它具有hasOnlyElementsOfType您接下来要调用的方法,因此即使在最近的 AssertJ 版本中也应该可以工作。

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

  • 感谢斯图尔特的详细分析!重大更改记录在 https://assertj.github.io/doc/#assertj-core-3-13-0-release-notes 中 (4认同)