Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring HATEOAS / MockMvc / JsonPath best practices

I'm writing unit tests for Spring HATEOAS backend using MockMvc and JsonPath. To test the links contained in a response I'm doing something like:

@Test
public void testListEmpty() throws Exception {
    mockMvc.perform(get("/rest/customers"))
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
            .andExpect(jsonPath("$.links", hasSize(1))) // make sure links only contains self link
            .andExpect(jsonPath("$.links[?(@.rel=='self')]", hasSize(1))) //  make sure the self link exists 1 time
            .andExpect(jsonPath("$.links[?(@.rel=='self')].href", contains("http://localhost/rest/customers{?page,size,sort}"))) // test self link is correct
            .andExpect(jsonPath("$.links[?(@.rel=='self')][0].href", is("http://localhost/rest/customers{?page,size,sort}"))) // alternative to test self link is correct
            .andExpect(jsonPath("$.content", hasSize(0))); // make sure no content elements exists
}

However I wonder if there are some best practices I should use to make it easier for myself like:

  • Testing link contains http://localhost does not feel right. Can I use some Spring MovkMvc helper to determine the host?
  • With JsonPath it's difficult to test if an array contains an element where 2 attributes have certain value. Like that the array should contain a self link with a certain value. Is there a better way to test that then above This will also come into play when testing validation errors for fields with error messages.

I've see technique like below in some blog posts:

.andExpect(jsonPath("$.fieldErrors[*].path", containsInAnyOrder("title", "description")))
.andExpect(jsonPath("$.fieldErrors[*].message", containsInAnyOrder(
    "The maximum length of the description is 500 characters.",
    "The maximum length of the title is 100 characters.")));

But this does not guarantee at all that title has the specific error message. It could also be that the title has incorrectly the "The maximum length of the description is 500 characters." but the test will succeed.

like image 324
Marcel Overdijk Avatar asked Aug 29 '14 14:08

Marcel Overdijk


1 Answers

You may use Traverson (included in Spring HATEOAS) to traverse the links in tests.

If you are using Spring Boot, I'd consider using @WebIntegrationTest("server.port=0") rather than MockMvc, as in some cases I experienced behaviours slightly different from the actual application.

You may find some example in a post of mine: Implementing HAL hypermedia REST API using Spring HATEOAS. Also look at the tests in the sample project.

like image 146
Nicus Avatar answered Oct 13 '22 14:10

Nicus