Как узнать, какое свойство объекта впервые не соответствует в JUnit assertEquals? - PullRequest
0 голосов
/ 21 мая 2019

У меня есть простой класс pojo в формате, показанном ниже.

class PojoClass {

    property1;
    ...
    propertyN;

    @override
    public int hashcode() {
        //implementation
    }

    @override
    public boolean equals(Object o) {
        //implementation
    }

    @override
    public String toString)() {
        return "PojoClass[property1= " + property1 ... propertyN + "]";
    }

}

В моем тестовом примере я делаю то, что мне нужно, и у меня есть ожидаемый PojoClass объект и фактический PojoClass объект.В некоторых случаях даже массивы (ожидаемые и фактические) объектов PojoClass.Когда assert терпит неудачу, я получаю сообщение, которое печатает toString ожидаемого и фактического.

toString недостаточно удобно в этом случае, поскольку мой объект PojoClass содержит от 20 до 30 свойств.Я должен вручную проверить все свойства, если они совпадают или нет.Есть ли способ в JUnit, чтобы напрямую указать, если какое свойство ожидаемого объекта не совпадает со свойством реального объекта?

Ответы [ 3 ]

1 голос
/ 21 мая 2019

Я считаю, что в jUnit такой функции нет.

Метод assertEquals в конечном итоге вернет expected.equals(actual), возможно, вы сможете изменить реализацию метода equals таким образом, чтобы он регистрировал, какие свойства, если таковые имеются, не совпадают, в результате чего метод equals возвращает false.

1 голос
/ 21 мая 2019

вы можете попробовать перехватить исключение ComparisonFailure, как показано ниже
PS Выполнить по одному утверждению за раз, то есть прокомментировать другое, чтобы увидеть, какое исключение перехватывается

@org.junit.Test
public void someSimpleTest() {
    try {
        Assert.assertEquals("123", "456");//Throw ComparisonFailure 
        Assert.assertArrayEquals(new String[] {"ABC","efg"}, new String[] {"ABCe","xys"});//Throw ArrayComparisonFailure 
    } catch(ComparisonFailure e) {
        System.out.println("Inside block");
        System.out.println(e);
    } catch(ArrayComparisonFailure e) {
        System.out.println("Inside block");
        System.out.println(e);
    }
}

в этом примере, если я прокомментирую seertEquals и выполнюassertArrayEquals, он будет четко печатать оператор

arrays first differed at element [0]; expected:<ABC[]> but was:<ABC[e]>

Следовательно, чтобы ответить на ваш вопрос. Есть ли какой-либо способ в JUnit, напрямую указать, если какое свойство ожидаемого объекта не совпадает со свойством реального объекта?

Это ясно говорит о том, что первый элемент не равен, следовательно, он потерпел неудачу.

Аналогично, вы можете проверить ваши различия toString.

http://junit.sourceforge.net/javadoc/org/junit/ComparisonFailure.html

Обновление для пользовательского объекта Этот код будет печатать только разницу между toString объекта

class PojoClass {

    String prop1;
    int prop2;
    String prop3;

    public  PojoClass(String prop1, int prop2, String prop3) {
        this.prop1 = prop1;
        this.prop2 = prop2;
        this.prop3 = prop3;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        PojoClass other = (PojoClass) obj;
        if (prop1 == null) {
            if (other.prop1 != null)
                return false;
        } else if (!prop1.equals(other.prop1))
            return false;
        if (prop2 != other.prop2)
            return false;
        if (prop3 == null) {
            if (other.prop3 != null)
                return false;
        } else if (!prop3.equals(other.prop3))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "PojoClass [prop1=" + prop1 + ", prop2=" + prop2 + ", prop3=" + prop3 + "]";
    }

Junit для печати ошибки подтвержденияразница

@org.junit.Test
    public void someSimpleTest() {
        try {   
            PojoClass class1 = new PojoClass("Sample", 1, "foo");
            PojoClass class2 = new PojoClass("Sample1", 1, "foo2");
            Assert.assertEquals(class1, class2);
        } catch(AssertionError e) {
            getStringDiff(e);
        }
    }

    private void getStringDiff(AssertionError e) {
        String msg = e.getMessage();
        String str1 = msg.substring(msg.indexOf("<"), msg.indexOf(">")+1);
        String str2 = msg.substring(msg.lastIndexOf("<"), msg.lastIndexOf(">")+1);
        System.out.println(StringUtils.difference(str1, str2));
    }
0 голосов
/ 28 мая 2019

Решение с использованием Gson.Основная идея этого решения состоит в том, чтобы получить значения объектов из toString и десериализовать его в Json, а затем использовать метод Maps.difference в библиотеке Gson, чтобы сравнить два Json и выяснить, какиезначение свойства (s) или key (s) - несоответствие.

  1. Обновление строки Pojo для получения строки json этого конкретного объекта POJO
class PojoClass {

    property1;
    ...
    propertyN;

    @override
    public int hashcode() {
        //implementation
    }

    @override
    public boolean equals(Object o) {
        //implementation
    }

    @override
    public String toString)() {
        return new Gson().toJson(this);
    }

}
Контрольный пример должен выглядеть следующим образом, как указал Аид .
@Test
public void pojoClassTest() throws Exception {
    List<PojoClass> sourcePojoList = getSourcePojoList();
    List<PojoClass> targetPojoList = getTargetPojoList();
    try {
        Assert.assertArrayEquals(sourcePojoList.toArray(), targetPojoList.toArray());
    }
    catch (ArrayComparisonFailure e) {
        Assert.fail(getMessage(e));
    }
}
Метод getMessage - это то, где мы получаем существующее сообщение от JUnit, создаем два Json s и сравниваем их.См. этот пост для техники сравнения.
// The junit error message will be in following format
// java.lang.AssertionError: arrays first differed at element [0]; expected:<{json}> but was:<{json}>
// So we get both source and target Json, and throw in the magic of gson library
// We compare them using method mentioned in link above.
// Now the new message that will be asserted contains message like below (assuming property 1 of the object is the mismatch)
// not equal: value differences={property1=("expected","actual")}

private static String getMessage(AssertionError e) throws IOException {
    String msg = e.getMessage();
    String sourceJson = msg.substring(msg.indexOf("expected:<") + 10, msg.indexOf("> but was:"));
    String targetJson = msg.substring(msg.lastIndexOf("but was:<") + 9, msg.lastIndexOf(">"));
    Gson g = new Gson();
    Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
    Map<String, Object> firstMap = g.fromJson(sourceJson, mapType);
    Map<String, Object> secondMap = g.fromJson(targetJson, mapType);
    return Maps.difference(firstMap, secondMap).toString();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...