如何反射性地比较各个领域的POJO

时间:2014-12-05 23:52:58

标签: java unit-testing junit testng mockito

我基本上是在寻找一个单元测试框架,我可以用它来比较不覆盖equals和hascode方法的POJO。我看了JUnit,Test NG和Mockito,但他们似乎没有解决目的。

例如,请考虑以下代码:

public class CarBean { 

    private String brand;
    private String color;

    public CarBean (){
    }

    public CarBean (String brand, String color){
        this.brand= brand;
        this.color= color;
    }

    /**
     * @return the brand
     */
    public String getBrand() {
        return brand;
    }

    /**
     * @param the brand to set
     */
    public void setBrand(String brand) {
        this.brand= brand;
    }

    /**
     * @return the color
     */
    public String getColor() {
        return color;
    }

    /**
     * @param the color to set
     */
    public void setColor(String color) {
        this.color= color;
    }
}

POJO CarBean代表一辆真实世界的汽车。它有两个参数,品牌和颜色。现在,假设您有两个汽车对象,如下所示:

CarBean car1 = new CarBean("Ford","Black");
CarBean car2 = new CarBean("Ford","Black");

两个对象都具有相同的参数值。但是当你用equals比较它时,它返回false:

car1.equals(car2); // This returns false

现在我需要对返回CarBean对象的方法进行单元测试。在这种情况下,我要么需要逐个比较carbean属性,要么我需要实现equals()和hashcode()方法。

所以我的问题是 - 是否已经有一个单元测试框架可以处理这个?

5 个答案:

答案 0 :(得分:4)

这种类型的反射在Hamcrest中构建为SamePropertyValuesAs,它比较了bean命名的属性(getFoo,isBar),而不是可能为它们提供动力的字段。核心Hamcrest支持内置于JUnit中,因此您只需添加包含SamePropertyValuesAs匹配器的Hamcrest库。

assertThat(car1, samePropertyValuesAs(car2));

答案 1 :(得分:4)

Unitils似乎确实解决了我的目的。以下API可以反射性地比较对象。即使POJO本身的属性是用户定义的POJO,它也可以进行比较:

import static org.unitils.reflectionassert.ReflectionAssert.*;

// Exact field-by-field comparison
assertReflectionEquals(new Person("John", "Doe", new Address("New street", 5, "Brussels")), 
                                 new Person("John", "Doe", new Address("New street", 5, "Brussels"));

// Ignore Null / 0 values in the expected object
assertReflectionEquals(new Person("John", null, new Address("New street", 0, null)),
                                 new Person("John", "Doe", new Address("New street", 5, "Brussels"), 
                                 ReflectionComparatorMode.IGNORE_DEFAULTS); 

// Ignore collection order
assertReflectionEquals(Arrays.asList(new Person("John"), new Person("Jane")),
                                 new Person[] {new Person("Jane"), new Person("John")}, 
                                 ReflectionComparatorMode.LENIENT_ORDER);

// Ignore null/0 values + collection order
assertLenientEquals(Arrays.asList(new Person("John"), null),
                                 new Person[] {new Person("Jane", "Doe"), new Person("John", "Doe")});

// Check only the firstName property 
assertPropertyLenientEquals("firstName", Arrays.asList("John", "Jane"),
                                 new Person[] {new Person("Jane", "Doe"), new Person("John", "Doe")});

Unitils Cookbook

的更多信息

答案 2 :(得分:4)

覆盖pojo类中的toString()方法,如下所示

venue

如果您有大量参数,我建议您使用以下代码

@Override
public String toString() {
    return "brand: " + this.brand + ",color: " + this.color;
}


car1.toString().equals(car2.toString()); //It will return true if both objects has same values

答案 3 :(得分:2)

因为这可能是使用反射"反射等于"是一个合理的搜索词,Google确实发现:

http://www.unitils.org/tutorial-reflectionassert.html

答案 4 :(得分:-3)

没有什么可以阻止你写自己的比较

使用JUnit:

编写一个静态方法,它接受2个对象并执行你想要的断言:

public static void sameBrandAndColor(Car expected, Car actual){
     assertEquals(expected.getBrand(), actual.getBrand());
     assertEquals(expected.getColor(), actual.getColor());
}

然后在你的测试中,只需调用你的比较方法。

@Test
public void test(){
    ...
    sameBrandAndColor(car1, car2);
}