Matcher for JSONPath expression to find order of fields
Asked Answered
I

1

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.

Irreformable answered 8/12, 2017 at 17:4 Comment(1)
See #55269536Collywobbles
I
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)));
Irreformable answered 8/12, 2017 at 18:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.