2

I have an API that returns a JSON object that will be displayed in a UI. The order of the fields in the object matters because the UI wants to display the fields in that order. I want to write a unit test to ensure the order of the fields in the object is correct. My API response looks like this:

{
    "data": {
        "field1": "value1",
        "field2": "value2"
     }
}

Using spring boot's MockMvc library, I want to write an expression like this to validate that the fields are coming back in order:

.andExpect(jsonPath("$.data"), is("field1=value1, field2=value2")

Obviously, the above doesn't work but I'm not sure what type of Matcher I should be using to try and validate that the fields are in order.

thrillstone
  • 31
  • 1
  • 4
  • 1
    See https://stackoverflow.com/questions/55269036/spring-mockmvc-match-a-collection-of-json-objects-in-any-order – Tom Sep 30 '20 at 07:18

1 Answers1

1

I couldn't find a Hamcrest matcher that compares the order of the fields, but it is easy enough to write your own. Note that the result of the JSON path expression will give you a LinkedHashMap so all you need is a Matcher that takes in a LinkedHashMap and compares it to the given object, entry by entry in order. Converting the map to a List of entries and using the equals method of List does the trick since List will compare items in order.

Here's how the matcher looks:

private class OrderedMapMatcher extends BaseMatcher<Map<String, String>> {

    private LinkedHashMap<String, String> expected;

    public OrderedMapMatcher(LinkedHashMap<String, String> expected) {
        this.expected = expected;
    }

    @Override
    public boolean matches(Object o) {
        if (!(o instanceof LinkedHashMap)) {
            return false;
        }
        LinkedHashMap actual = (LinkedHashMap) o;
        List<Map.Entry<String, String>> expectedList = new ArrayList<>(expected.entrySet());
        List actualList = new ArrayList(actual.entrySet());
        return expectedList.equals(actualList);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText(expected.toString());
    }
}

And here's how the assertion looks:

LinkedHashMap<String, String> expectedData = new LinkedHashMap<>();
expectedData.put("field1", "value1");
expectedData.put("field2", "value2");

// mockMvc ResultActions code would be here
.andExpect(jsonPath("$.data", new OrderedMapMatcher(expectedData)));
thrillstone
  • 31
  • 1
  • 4