AssertJ:`ignoringFields` 是不是忽略了所有提供的字段?

AssertJ: `ignoringFields` is not ignoring all the provided fields?

我想使用版本 3.14.0:

中的 org.assertj.core.api.Assertions.assertThat 来比较两个对象
assertThat(getActual())
        .usingRecursiveComparison()
        .ignoringFields("customer", "orders", "$hashCode", "fragments.parentFields.__typename", "fragments.parentFields.image")
        .isEqualTo(orderForm)

当我这样做时,出现以下错误:

when recursively comparing field by field, but found the following difference:

field/property 'fragments' differ:
- actual value   : Fragments{parentFields=Optional[ParentFields{__typename=OrderForm, id=1, image=Image{__typename=Image, id=71, accuracy=100.0, type=ORDER_FORM, state=AUTOMATIC, value=order form, base64=}}]}
- expected value : Fragments{parentFields=Optional[ParentFields{__typename=ParentFields, id=1, image=Image{__typename=Image, id=123, accuracy=99.99, type=NONE, state=NONE, value=value, base64=base64}}]}

The recursive comparison was performed with this configuration:
- the following fields were ignored in the comparison: customer, orders, $hashCode, fragments.parentFields.__typename, fragments.parentFields.image
- overridden equals methods were used in the comparison
- these types were compared with the following comparators:
  - java.lang.Double -> DoubleComparator[precision=1.0E-15]
  - java.lang.Float -> FloatComparator[precision=1.0E-6]
- actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior).

根据我的理解,忽略我添加到 ignoreingFields 函数的所有文件,比较应该是:

- actual value   : Fragments{parentFields=Optional[ParentFields{id=1}]}
- expected value : Fragments{parentFields=Optional[ParentFields{id=1}]} 

因此它不应该失败,它应该成功。

其他被忽略的字段(customerorders$hashCode)被正确忽略。所以我想知道嵌套对象的字段是否有问题。但是在 javadoc 中我发现:

* // assertion succeeds as name and home.address.street fields are ignored in the comparison
* assertThat(sherlock).usingRecursiveComparison()
*                     .ignoringFields("name", "home.address.street")
*                     .isEqualTo(noName);

所以我认为我正在按照 API 的意图使用它。

当然我可以通过简单地解决所有这些问题:

assertThat(actual
        ?.fragments()
        ?.parentFields()
        ?.get()
        ?.id()
).isEqualTo(orderForm
        .fragments()
        .parentFields()
        .get()
        .id())

但是我有很多对象我必须像那样进行比较并且它们没有相同的超级 class。 所以我要创建类似的东西:

fun assertCommons(actual: Any, expected: Any) {
    assertThat(actual)
        .usingRecursiveComparison()
        ....
}

回到问题:忽略这些字段有什么问题?

编辑

因为 parentFields 是可选的:

...
.ignoringFields("customer", "orders", "$hashCode", "fragments.parentFields.get().__typename", "fragments.parentFields.get().image")
...
field/property 'fragments' differ:
- actual value   : Fragments{parentFields=Optional[ParentFields{__typename=OrderForm, id=1, image=Image{__typename=Image, id=71, accuracy=100.0, type=ORDER_FORM, state=AUTOMATIC, value=order form, base64=}}]}
- expected value : Fragments{parentFields=Optional[ParentFields{__typename=ParentFields, id=1, image=Image{__typename=Image, id=123, accuracy=99.99, type=NONE, state=NONE, value=value, base64=base64}}]}

The recursive comparison was performed with this configuration:
 - the following fields were ignored in the comparison: customer, orders, $hashCode, fragments.parentFields.get().__typename, fragments.parentFields.get().image
 - overridden equals methods were used in the comparison
 - these types were compared with the following comparators:
 - java.lang.Double -> DoubleComparator[precision=1.0E-15]
 - java.lang.Float -> FloatComparator[precision=1.0E-6]
 - actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior).

value代替get()

...
.ignoringFields("customer", "orders", "$hashCode", "fragments.parentFields.value.__typename", "fragments.parentFields.value.image")
...
when recursively comparing field by field, but found the following difference:

field/property 'fragments' differ:
- actual value   : Fragments{parentFields=Optional[ParentFields{__typename=OrderForm, id=1, image=Image{__typename=Image, id=71, accuracy=100.0, type=ORDER_FORM, state=AUTOMATIC, value=order form, base64=Optional[]}}]}
- expected value : Fragments{parentFields=Optional[ParentFields{__typename=ParentFields, id=1, image=Image{__typename=Image, id=123, accuracy=99.99, type=NONE, state=NONE, value=value, base64=Optional[base64]}}]}

The recursive comparison was performed with this configuration:
- the following fields were ignored in the comparison: customer, orders, $hashCode, fragments.parentFields.value
- overridden equals methods were used in the comparison
- these types were compared with the following comparators:
  - java.lang.Double -> DoubleComparator[precision=1.0E-15]
  - java.lang.Float -> FloatComparator[precision=1.0E-6]
- actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior).

"fragments.parentFields.get().__typename" 不是您打算执行的有效声明。当指定 "a.b.c" 时,AssertJ 将尝试查找 getA().getB().getC()a.b.c 或 field/getter 的组合(如 getA().b.getC().

指定 fragments.parentFields.get() 将不起作用,因为没有名为 get() 的字段。尝试使用 value 代替,因为这是 get() 返回的字段(AssertJ 可以读取私有字段)。