assertThat(actual).usingRecursiveComparison().ignoringAllOverriddenEquals().isEqualTo(expected) 的奇怪行为
Strange behavior of assertThat(actual).usingRecursiveComparison().ignoringAllOverriddenEquals().isEqualTo(expected)
我在 assertj 库中发现了一个有趣的递归比较行为。如果您比较 类 的对象是子 类,那么在比较过程中似乎会跳过 super 类 的字段。这是一个已知问题吗?还是我做错了什么?这是一个简短的例子:
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class ExampleTest {
@Test
public void test() {
MyException expected =
new MyException("Expected text message");
MyException actual = new MyException("Actual text message"); //values for the field Throwable.detailMessage are different
assertThat(actual).usingRecursiveComparison().ignoringAllOverriddenEquals().isEqualTo(expected);
}
}
class MyException extends RuntimeException {
MyException(String message) {
super(message);
}
}
这个测试会在实际上不应该通过的时候通过,因为 actual.getMessage()
和 expected.getMessage()
会显示不同的值。
显然,该库跳过了从驻留在 java.lang
中的超类继承的字段的比较。由于 MyException
正在使用从 java.lang.Throwable
继承的 detailMessage
字段,因此将被跳过。
这是来自 org.assertj.core.internal.Objects
的代码,似乎是造成这种行为的原因:
/**
* Returns the declared fields of given class and its superclasses stopping at superclass in <code>java.lang</code>
* package whose fields are not included.
*
* @param clazz the class we want the declared fields.
* @return the declared fields of given class and its superclasses.
*/
public static Set<Field> getDeclaredFieldsIncludingInherited(Class<?> clazz) {
checkNotNull(clazz, "expecting Class parameter not to be null");
Set<Field> declaredFields = getDeclaredFieldsIgnoringSyntheticAndStatic(clazz);
// get fields declared in superclass
Class<?> superclazz = clazz.getSuperclass();
while (superclazz != null && !superclazz.getName().startsWith("java.lang")) {
declaredFields.addAll(getDeclaredFieldsIgnoringSyntheticAndStatic(superclazz));
superclazz = superclazz.getSuperclass();
}
return declaredFields;
}
我在 assertj 库中发现了一个有趣的递归比较行为。如果您比较 类 的对象是子 类,那么在比较过程中似乎会跳过 super 类 的字段。这是一个已知问题吗?还是我做错了什么?这是一个简短的例子:
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class ExampleTest {
@Test
public void test() {
MyException expected =
new MyException("Expected text message");
MyException actual = new MyException("Actual text message"); //values for the field Throwable.detailMessage are different
assertThat(actual).usingRecursiveComparison().ignoringAllOverriddenEquals().isEqualTo(expected);
}
}
class MyException extends RuntimeException {
MyException(String message) {
super(message);
}
}
这个测试会在实际上不应该通过的时候通过,因为 actual.getMessage()
和 expected.getMessage()
会显示不同的值。
显然,该库跳过了从驻留在 java.lang
中的超类继承的字段的比较。由于 MyException
正在使用从 java.lang.Throwable
继承的 detailMessage
字段,因此将被跳过。
这是来自 org.assertj.core.internal.Objects
的代码,似乎是造成这种行为的原因:
/**
* Returns the declared fields of given class and its superclasses stopping at superclass in <code>java.lang</code>
* package whose fields are not included.
*
* @param clazz the class we want the declared fields.
* @return the declared fields of given class and its superclasses.
*/
public static Set<Field> getDeclaredFieldsIncludingInherited(Class<?> clazz) {
checkNotNull(clazz, "expecting Class parameter not to be null");
Set<Field> declaredFields = getDeclaredFieldsIgnoringSyntheticAndStatic(clazz);
// get fields declared in superclass
Class<?> superclazz = clazz.getSuperclass();
while (superclazz != null && !superclazz.getName().startsWith("java.lang")) {
declaredFields.addAll(getDeclaredFieldsIgnoringSyntheticAndStatic(superclazz));
superclazz = superclazz.getSuperclass();
}
return declaredFields;
}