2017-07-26 2 views
1

Ich versuche, einen Unit-Test mit JUnit zu schreiben, ich möchte eine Funktion mit AssertsEqual testen, wo ich zwei Listen von JsonObjects habe. Unten sind meine tatsächlichen und erwarteten JSON Strings.Vergleichen Sie zwei identische Json-Listen mit Objekten und Feldern innerhalb von Objekten in unterschiedlicher Reihenfolge

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 
          } 
      ] 

In dem obigen Beispiel kann man sehen, dass das Objekt, um für die erwartete Zeichenfolge und die Reihenfolge der einzelnen Felder auch innerhalb der einzelnen Objekte geändert geändert wird.

Bitte meinen Testfall unten finden:

@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); 

Die obige Funktion auch falsch zurück, wenn die gleiche Zeichenfolge zur Verfügung gestellt wird, um die Reihenfolge zu ändern. Ich möchte, dass diese Funktion als wahr zurückgibt, wenn der Inhalt der Zeichenfolge unabhängig von der Reihenfolge gleich ist.

+0

* Was haben Sie bisher versucht * zeigen uns einige Code bitte – Lino

+0

Einheit Testfall gegeben. – Salam

+0

Während ich verstehe, was Sie hier versuchen, bin ich besorgt, dass Sie eine ziemlich kritische Information vermissen. JSON-Arrays, die anders angeordnet sind, sind _nicht_ gleich. –

Antwort

1

Zwei Optionen aus der Spitze von meinem Kopf:

werfen sie alle in einen Set, und vergleichen Sie die Sätze:

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

Das wird nicht funktionieren, wenn Ihre Listen Duplikate enthalten.


Alternativ können Sie auch die Listen vor dem Vergleich sortieren. Jede beliebige Sortierung funktioniert, sofern sie konsistent ist.

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

Unit-Testfall hinzugefügt, könnten Sie einen Blick darauf werfen? – Salam

+0

Kann Collections.sort nicht verwenden, da das 'Foo' (JsonObject) nicht vergleichbar ist. – Salam

+0

Ah. Das ist ein Schmerz. Konvertiere sie zuerst in Zeichenfolgen. – Michael

3

Haben Sie JSONUnit überprüft?

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

Es ist Beschreibung:

JsonUnit ist eine Bibliothek, die JSON-Vergleich in Unit-Tests vereinfacht.

Wenn Sie Maven verwenden könnten Sie ein Projekt wie dieses erstellen:

<?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> 

Dann können Sie einen JUnit-Test wie dieser hier schreiben:

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)); 
    } 
} 

OK, wenn Sie Sie können JSON Unit nicht verwenden. Sie könnten versuchen, den Inhalt der JSON-Listen, die Sie vergleichen möchten, zu hashen, die Hashes zu sortieren und dann die Hash-Listen zu vergleichen. Hier ist ein kleines Beispiel mit Jackson, JUnit 5 und 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()); 
} 
+0

Danke, ich bin auf diese Bibliothek gestoßen, aber ich brauche eine Lösung, ohne zusätzliche Abhängigkeiten hinzuzufügen. – Salam

+0

Das ist ein bisschen eine Schande. Es schien mir, dass Ihre Anforderungen perfekt zu dieser Bibliothek passen.Es kann Listenvergleiche "unabhängig von der Reihenfolge" wie gewünscht durchführen. –

+0

Ich stimme Ihrer Lösung vollkommen zu, aber ich bin nur eingeschränkt, um zusätzliche Abhängigkeiten hinzuzufügen :) – Salam

Verwandte Themen