将两个相同的json列表与对象中的对象和字段按不同顺序进行比较

时间:2017-07-26 14:08:04

标签: java junit

我正在尝试使用JUnit编写单元测试,我想使用AssertsEqual测试一个函数,其中我有两个JsonObject列表。以下是我的实际和预期的json字符串。

String jsonOutput = [ {
                       id: 1,
                       name: abc,
                       age: 23
                      },
                      {
                       id: 2,
                       name: efg,
                       age: 26
                      },
                      {
                       id: 3,
                       name: rst,
                       age: 26
                      }
     ]


   String jsonExpected = [ {
                            id: 2,
                            name: efg,
                            age: 26
                           },
                           {  
                            id: 1,
                            age: 23,
                            name: abc
                           },
                           {
                            id: 3,
                            name: rst,
                            age: 26
                           }
             ]

在上面的示例中,可以看到对象顺序已针对预期字符串进行更改,并且各个字段的顺序也在各个对象中更改。

请在下面找到我的测试用例:

   @Test
public void testApply() {
    Command command = new Command();
    Logger logger = LoggerFactory.getLogger(Command.class.getName());
    command.set(logger, new JsonObject());
    command.apply(Buffer.buffer(TestConstants.ALL_GAPS));
    Object eventList = command.apply(Buffer.buffer(TestConstants.OCCUPIED_GAPS)); // returns a list of json objects
    List<JsonObject> expectedList = createExpectedEventList(TestConstants.EVENT_LIST);
    Assert.assertEquals(expectedList, eventList);
}

private List<JsonObject> createExpectedEventList(String eventListString) {
    JsonArray eventArray = new JsonArray(eventListString);
    List<JsonObject> eventList = new ArrayList<>();
    for (Object obj : eventArray) {
        eventList.add((JsonObject) obj);
    }
    return eventList;
}


    Assert.assertEquals(expectedList, eventList);

即使提供了改变顺序的相同字符串,上述函数也会返回false。如果字符串的内容相同而不管顺序如何,我希望此函数返回true。

2 个答案:

答案 0 :(得分:3)

你检查过JSONUnit吗?

https://github.com/lukas-krecan/JsonUnit

它的描述是:

  

JsonUnit是一个简化单元测试中JSON比较的库。

如果您使用的是Maven,您可以创建一个类似这样的项目:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.fernandes</groupId>
    <artifactId>jsonunit.test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.8.8</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.8</version>
        </dependency>

        <dependency>
            <groupId>net.javacrumbs.json-unit</groupId>
            <artifactId>json-unit</artifactId>
            <version>1.25.0</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.0.0-M4</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

然后你可以在这里写一个像这样的JUnit测试:

package com.fernandes.jsonunit.test;

import org.junit.jupiter.api.Test;

import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
import static net.javacrumbs.jsonunit.JsonAssert.when;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;

/**
 * Created by Gil on 26/07/2017.
 */
public class ArraysTest {

    @Test
    void checkArrays() {
        String array1 = "{\"test\":[4,1,2,3]}";
        String array2 = "{\"test\":[1,2,3,4]}";
        assertJsonEquals(array1, array2, when(IGNORING_ARRAY_ORDER));
    }
}

好的,如果您不能使用JSON Unit,您可以尝试散列要比较的JSON列表的内容,对哈希值进行排序,然后比较哈希列表。以下是使用Jackson,JUnit 5和Java 8的简单示例:

@Test
@DisplayName("When arrays equal, but in different order - match")
void checkArraysManual() throws IOException {
    String array1 = "[{\n" +
            "\"id\": 1,\n" +
            "\"name\": \"abc\",\n" +
            "\"age\": 23\n" +
            "},\n" +
            "{\n" +
            "\"id\": 2,\n" +
            "\"name\": \"efg\",\n" +
            "\"age\": 26\n" +
            "},\n" +
            "{\n" +
            "\"id\": 3,\n" +
            "\"name\": \"rst\",\n" +
            "\"age\": 26\n" +
            "}]";

    String array2 = "[{\n" +
            "\"id\": 2,\n" +
            "\"name\": \"efg\",\n" +
            "\"age\": 26\n" +
            "},\n" +
            "{\n" +
            "\"id\": 1,\n" +
            "\"name\": \"abc\",\n" +
            "\"age\": 23\n" +
            "},\n" +
            "{\n" +
            "\"id\": 3,\n" +
            "\"name\": \"rst\",\n" +
            "\"age\": 26\n" +
            "}]";

    ObjectMapper mapper = new ObjectMapper();
    JsonNode root1 = mapper.readTree(array1);
    JsonNode root2 = mapper.readTree(array2);
    ArrayNode array1Node = (ArrayNode) root1;
    ArrayNode array2Node = (ArrayNode) root2;
    assertThat(compareArrayNodes(array1Node, array2Node), is(true));
}

private boolean compareArrayNodes(ArrayNode array1Node, ArrayNode array2Node) {
    if(array1Node.size() != array2Node.size()) {
        return false;
    }
    List<Integer> hashList1 = hashArrayNode(array1Node);
    List<Integer> hashList2 = hashArrayNode(array2Node);
    return hashList1.equals(hashList2);
}

private List<Integer> hashArrayNode(ArrayNode array1Node) {
    Iterable<JsonNode> supplier = array1Node::elements;
    return StreamSupport.stream(supplier.spliterator(), false)
            .map(Objects::hashCode).sorted()
            .collect(Collectors.toList());
}

答案 1 :(得分:1)

我头顶的两个选项:

将它们全部投入Set,然后比较这些集:

Set<Foo> a = new HashSet<>(first);
Set<Foo> b = new HashSet<>(second);
assertEquals(a, b);

如果您的列表包含重复项,则无法使用。

或者,只需在比较之前对列表进行排序。任何任意排序都可以,只要它是一致的。

List<Foo> a = Collections.sort(new ArrayList<>(first));
List<Foo> b = Collections.sort(new ArrayList<>(second));
assertEquals(a, b);