我正在编写一些网络驱动程序测试,用于验证网页。页面主要包含网页表格。我将我的测试数据存储在对象中,因此我将预期的对象传递给测试并将其与网页中的实际对象进行比较。测试数据对象非常简单,大部分只包含一堆字符串:
public class PetOwnerDTO {
private String ownerPhoneNr;
private String ownerEmail;
private String ownerAddress;
// getters and setters skipped
}
现在因为有很多不同的对象需要验证,我正在尝试开发一个通用的对象比较器来为我做这件事。我已经拥有的:
package Helpers;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.List;
import static junit.framework.TestCase.fail;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalToIgnoringCase;
public class ObjectComparer {
public static void compareObjects(Object obj1, Object obj2) {
assertThat(obj1, is(notNullValue()));
assertThat(obj2, is(notNullValue()));
Class obj1Class = obj1.getClass();
Class obj2Class = obj2.getClass();
assertThat(obj1Class, is(sameInstance(obj2Class)));
if (obj1Class.isArray()) {
assertThat("Object2 is not an array", (obj2Class.isArray()));
assertThat(Array.getLength(obj1), is(equalTo(Array.getLength(obj2))));
for (int i = 0; i < Array.getLength(obj1); i++) {
Object value1 = Array.get(obj1, i);
Object value2 = Array.get(obj2, i);
compareObjects(value1, value2);
}
}
if (obj1 instanceof List<?>){
throw new RuntimeException("Lists not supported, use looping");
}
Field[] fieldsObj1 = obj1Class.getDeclaredFields();
Field[] fieldsObj2 = obj2Class.getDeclaredFields();
assertThat(fieldsObj1.length, is(equalTo(fieldsObj2.length)));
for (int i = 0; i < fieldsObj1.length; i++) {
fieldsObj1[i].setAccessible(true);
fieldsObj2[i].setAccessible(true);
try {
Object valueObj1 = fieldsObj1[i].get(obj1);
Object valueObj2 = fieldsObj2[i].get(obj2);
assertThat(valueObj1.toString(), is(equalToIgnoringCase(valueObj2.toString())));
} catch (IllegalAccessException e) {
fail("Unable to compare objects");
}
}
}
}
问题出在第二个if:
if (obj1 instanceof List<?>){
如何从列表中获取对象?类似于 Array.get()
的东西?
或者有更好的方法吗?
最佳答案
看起来您正试图避免在每个测试对象中实现 equals()
。我觉得这是个坏主意。有许多方法可以加快 equals()
方法的执行速度,包括:
让您的 IDE 生成它。 Eclipse 当然支持这个想法。
依赖第三方库,例如 Apache Commons Lang
EqualsBuilder
,这可能看起来很简单:@Override public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj); }
我强烈建议您采用这些方法中的一种,而不是构建一个狡猾的基于反射的类来逐个字段地测试相等性。拥有适当的相等方法有很多好处,包括:
- 将这些项目放入集合时的正确行为。
- 能够调用普通的 JUnit 断言(
assertEquals()
等)
当您更改equals()
时,不要忘记编写一个hashCode()
方法。同样,有一些快捷方式(包括 HashCodeBuilder
)。
关于java - 使用反射从列表中获取对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21186621/