Java 使用反射从列表中获取对象

Java 使用反射从列表中获取对象,java,testing,reflection,comparison,automated-tests,Java,Testing,Reflection,Comparison,Automated Tests,我正在编写一些webdriver测试,用于验证网页。页面主要包含web表。我将测试数据存储在对象中,以便将预期对象传递给测试,并将其与网页中的实际对象进行比较。测试数据对象非常简单,大部分只包含一组字符串: public class PetOwnerDTO { private String ownerPhoneNr; private String ownerEmail; private String ownerAddress; // getters and set

我正在编写一些webdriver测试,用于验证网页。页面主要包含web表。我将测试数据存储在对象中,以便将预期对象传递给测试,并将其与网页中的实际对象进行比较。测试数据对象非常简单,大部分只包含一组字符串:

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");
            }
        }
    }
}
包助手;
导入java.lang.reflect.Array;
导入java.lang.reflect.Field;
导入java.util.List;
导入静态junit.framework.TestCase.fail;
导入静态org.hamcrest.CoreMatchers.*;
导入静态org.hamcrest.matcherasert.assertThat;
导入静态org.hamcrest.Matchers.equalToIgnoringCase;
公共类对象比较器{
公共静态无效比较对象(对象obj1、对象obj2){
断言(obj1,是(notNullValue());
断言(obj2,is(notNullValue());
类obj1Class=obj1.getClass();
类obj2Class=obj2.getClass();
资产(obj1Class,is(sameInstance(obj2Class));
if(obj1Class.isArray()){
断言(“Object2不是数组”,(obj2Class.isArray());
断言(Array.getLength(obj1)是(equalTo(Array.getLength(obj2)));
对于(int i=0;i
如果出现以下情况,则第二个问题存在:

if (obj1 instanceof List<?>){
if(obj1实例列表){
如何从列表中获取对象?类似于
Array.get()

或者有更好的方法吗?

看起来您试图避免在每个测试对象中实现
equals()
。我觉得这是个坏主意。有很多方法可以加快
equals()
方法的实现,包括:

  • 让您的IDE生成它。Eclipse当然支持这个想法

  • 依赖第三方库,如Apache Commons Lang,它看起来很简单:

    @Override
    public boolean equals(Object obj) {
      return EqualsBuilder.reflectionEquals(this, obj);
    }
    
我强烈建议您采用这些方法中的一种,而不是构建一个狡猾的基于反射的类,在一个字段一个字段的基础上测试平等性。使用适当的平等性方法有很多好处,包括:

  • 将这些项目放置在一个集合中时,应纠正其行为
  • 能够调用普通JUnit断言(
    assertEquals()
    等)

当您更改
equals()
时,不要忘记编写一个
hashCode()
方法。同样,还有一些快捷方式(包括)。

看起来您试图避免在每个测试对象中实现
equals()
。这让我觉得是个坏主意。有很多方法可以加速
equals()的实现
方法,包括:

  • 让您的IDE生成它。Eclipse当然支持这个想法

  • 依赖第三方库,如Apache Commons Lang,它看起来很简单:

    @Override
    public boolean equals(Object obj) {
      return EqualsBuilder.reflectionEquals(this, obj);
    }
    
我强烈建议您采用这些方法中的一种,而不是构建一个狡猾的基于反射的类,在一个字段一个字段的基础上测试平等性。使用适当的平等性方法有很多好处,包括:

  • 将这些项目放置在一个集合中时,应纠正其行为
  • 能够调用普通JUnit断言(
    assertEquals()
    等)

当您更改
equals()
时,不要忘记编写一个
hashCode()
方法。同样,还有一些快捷方式(包括)。

您可以尝试列表API的toArray()-方法。请注意,您必须有相同数量的列表项才能正确比较。

您可以尝试toArray()-列表API的方法。请注意,您必须拥有相同数量的列表项才能正确地进行比较。

这很酷,但问题是,目前在使用ie Assert.assertTrue(obj1.equals(obj2)时,我只收到一个AssertOnError(或者我可能会以某种方式记录它),而我自己使用AssertIt的方式给了我:“预期的:abc实际的:dsg”.即使使用assertThat与该值相等,我所能得到的最好结果也是:true get:false@ErkiM.我已经写了一个
DifferenceBuilder
,它可能会完全满足您的要求。我希望它能在2月份的某个时候发布。@ErkiM。自从写了最后一条评论后,我已经成为Apache Commons的提交者,也是我的第一个行动将代码添加到主干中。一个新版本将在下周左右发布。请关注commons网站或关注公告。这很酷,但问题是,目前,在使用ie Assert.assertTrue(obj1.equals(obj2)时,我只收到AssertOnError(或者我可能会以某种方式记录它),而我自己使用assertThat的方式给了我:“Expected:abc-Actual:dsg”。即使使用assertThat与它相等,最好的