0

I want to make tests for create and update APIs in Spring Boot:

@Test
public void shouldCreateNewUser() throws Exception, UserAlreadyExistException {

    User user = User.builder()
            .id(10L)
            .firstName("Alin")
            .lastName("Balan")
            .mail("alin@yahoo.com")
            .password("pass")
            .isAdmin(true)
            .role(Roles.PTE)
            .build();

    mvc.perform(MockMvcRequestBuilders.post("/api/users")
            .contentType(MediaType.APPLICATION_JSON)
            .content(mapper.writeValueAsString(user)))
            .andExpect(status().isOk())
            .andExpect(MockMvcResultMatchers.jsonPath("$[10].id",is(10)));

    Mockito.verify(userService, Mockito.times(1)).save(Mockito.any());
}

But I have this error

java.lang.AssertionError: No value at JSON path "$[10].id", exception: json can not be null or empty

hc_dev
  • 8,389
  • 1
  • 26
  • 38

2 Answers2

0

Seeing how no answer has been posted so far despite the many comments, I'll summarize:

If your API endpoint POST /api/users expects and returns the following JSON:

{
    "id": 10,
    "firstName": "Alin",
    "lastName": "Balan",
    "mail": "alin@yahoo.com",
    "password": "pass",
    "isAdmin": true,
    "role": "PTE"
}

then you could query this JSON via jsonpath using:

$.id
$.firstName
...
$.isAdmin
$.role

not $[10].id. Here is a basic guide on jsonpath.

This means that your assertion should look like:

    mvc.perform(MockMvcRequestBuilders.post("/api/users")
            .contentType(MediaType.APPLICATION_JSON)
            .content(mapper.writeValueAsString(user)))
            .andExpect(status().isOk())
            .andExpect(MockMvcResultMatchers.jsonPath("$.id",is(10)));
filpa
  • 3,651
  • 8
  • 52
  • 91
  • I tried in this way..but same errors. Errors are: MockHttpServletResponse: Status = 200 Error message = null Headers = [] Content type = null Body = Forwarded URL = null Redirected URL = null Cookies = [] No value at JSON path "$.id" json can not be null or empty – Eugen Gîrlescu Jul 27 '21 at 05:21
  • What does your response look like? What does your endpoint return? – filpa Jul 27 '21 at 07:50
  • from a post you should expect 201, not 200. Something's off with your api – njzk2 Jul 27 '21 at 20:33
  • @njzk2 That depends on their API implementation. `200 OK` is a valid response code on `POST`. The more RESTful approach, as you say, would be to return `201 Created`. – filpa Jul 28 '21 at 09:23
0

Searching for the complete error-message gave similar: No value at JSON path "$.name", exception: json can not be null or empty, Using Mockmvc and Spring-boot

Assumption on expected JSON response

When creating or updating a single user, you would expect a single user object as JSON response - not an array (with 10 user elements).

Then your assertion should check on the ID of the single object in JSON response - to be equal to 10:

mvc.perform(MockMvcRequestBuilders.post("/api/users")
   .contentType(MediaType.APPLICATION_JSON)
   .content(mapper.writeValueAsString(user)))
   .andExpect(status().isOk())
   .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
   .andExpect(
       MockMvcResultMatchers.jsonPath("$.id", is(10))
   )
);

Explanation

JSON-path is a formal expression to select nodes of a JSON tree (compare to XPath for selecting XML elements).

  • JSON-path expression $ denotes the root node
  • JSON-path $[10] evaluates to the 11th element (zero-based index!) of an array (at root).
  • JSON-path $.id evaluates to the field named id of an object (at root)

See also:

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • 1
    Minor note: `$[10]` would return the *11th* element, as `jsonpath` is 0-indexed. – filpa Jul 26 '21 at 22:15
  • I tried in this way..but same errors. Errors are: MockHttpServletResponse: Status = 200 Error message = null Headers = [] Content type = null Body = Forwarded URL = null Redirected URL = null Cookies = [] No value at JSON path "$.id" json can not be null or empty – Eugen Gîrlescu Jul 27 '21 at 05:26
  • @EugenGîrlescu Then please add `.andDo(MockMvcResultHandlers.print())` before `.andExpect` to verify the __actual JSON output__ in console. And please __edit & clarify your question__: Which JSON-response (format) is expected? Can you show the Controller-method and returning class. – hc_dev Jul 27 '21 at 06:01
  • @user991710 Thanks, great note - fixed & explained. – hc_dev Jul 27 '21 at 06:03