Gabriel Pulga
Gabriel Pulga

Reputation: 293

How to integration test a RESTful APIs PUT endpoint with TestRestTemplate?

I'm currently working on a Spring Boot CRUD RESTful API with an User entity that consists of two parameters : name and id. Its endpoints are :

Each endpoint is built with a controller and a service to implement its logic.

I've already wrote unit tests for my controllers and services, now i'm trying to build integration tests to assert that my endpoints work properly as a group of components.

No mocking involved, all this will be done by using the TestRestTemplate and asserting that every operation was executed correctly and every response checked with its expected value.

The following are the tests I've already built :

@SpringBootTest(classes = UsersApiApplication.class,
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {

    @LocalServerPort
    private int port;

    TestRestTemplate restTemplate = new TestRestTemplate();
    HttpHeaders headers = new HttpHeaders();

    private void instantiateNewUser() {
        User userNumberFour = new User();
        userNumberFour.setName("Four");
        userNumberFour.setId(4L);

        ResponseEntity<User> responseEntity = restTemplate
                .postForEntity(createURLWithPort("/users"), userNumberFour, User.class);
    }

    @Test
    public void createNewUserTest() {
        User testUser = new User();
        testUser.setName("Test User");
        testUser.setId(5L);

        ResponseEntity<User> responseEntity = restTemplate
                .postForEntity(createURLWithPort("/users"), testUser, User.class);

        assertEquals(201, responseEntity.getStatusCodeValue());
        assertEquals(responseEntity.getBody(), testUser);
    }


    @Test
    public void listSpecificUserTest() throws JSONException {

        instantiateNewUser();
        HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);

        ResponseEntity<String> responseEntity = restTemplate.exchange(
                createURLWithPort("/users/4/"),
                HttpMethod.GET, httpEntity, String.class);

        String expectedResponseBody = "{id:4,name:Four}";

        assertEquals(200, responseEntity.getStatusCodeValue());
        JSONAssert.assertEquals(expectedResponseBody, responseEntity.getBody(), false);
    }

    @Test
    public void listAllUsersTest() throws JSONException {

        instantiateNewUser();
        HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);

        ResponseEntity<String> responseEntity = restTemplate.exchange(
                createURLWithPort("/users"),
                HttpMethod.GET, httpEntity, String.class);

        //All instantiated users
        ArrayList<String> expectedResponseBody = new ArrayList<>(Collections.emptyList());
        expectedResponseBody.add("{id:1,name:Neo}");
        expectedResponseBody.add("{id:2,name:Owt}");
        expectedResponseBody.add("{id:3,name:Three}");
        expectedResponseBody.add("{id:4,name:Four}");

        assertEquals(200, responseEntity.getStatusCodeValue());
        JSONAssert.assertEquals(String.valueOf(expectedResponseBody), responseEntity.getBody(), false);
    }

    @Test
    public void deleteSpecificUserTest() throws JSONException {

        instantiateNewUser();
        HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);

        ResponseEntity<String> responseEntity = restTemplate.exchange(
                createURLWithPort("/users/4/"),
                HttpMethod.DELETE, httpEntity, String.class);

        assertEquals(204, responseEntity.getStatusCodeValue());
        JSONAssert.assertEquals(null, responseEntity.getBody(), false);
    }

    private String createURLWithPort(String uri) {
        return "http://localhost:" + port + uri;
    }
}

As you can see, it's missing the PUT request method test, which is the update endpoint. To implement its logic, i need to send a message body with the content that will override the old users characteristics, but how?

This is what i made so far :

    @Test
    public void updateSpecificUserTest() throws JSONException {
    
        instantiateNewUser();
        HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);
    
        ResponseEntity<String> responseEntity = restTemplate.exchange(
                createURLWithPort("/users/4/"),
                HttpMethod.PUT, httpEntity, String.class);

        String expectedResponseBody = "{id:4,name:Four Updated}";
    
        assertEquals(200, responseEntity.getStatusCodeValue());
        JSONAssert.assertEquals(expectedResponseBody, responseEntity.getBody(), false);
    }
    

Would appreciate if someone could help with this one, didn't found the answer online.

Upvotes: 0

Views: 3690

Answers (2)

Gabriel Pulga
Gabriel Pulga

Reputation: 293

So, the solution to my problem really was that I was sending a null request body in my httpEntity.

I also needed to set the content type to JSON :

@Test
    public void updateSpecificUserTest() throws JSONException, JsonProcessingException {

        instantiateNewUser();

        User updatedUser = new User();
        updatedUser.setName("Updated");
        updatedUser.setId(4L);

        ObjectMapper mapper = new ObjectMapper();
        String requestBody = mapper.writeValueAsString(updatedUser);

        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<String> httpEntity = new HttpEntity<String>(requestBody, headers);

        ResponseEntity<String> responseEntity = restTemplate.exchange(
                createURLWithPort("/users/4/"),
                HttpMethod.PUT, httpEntity, String.class);

        String expectedResponseBody = "{id:4,name:Updated}";

        assertEquals(200, responseEntity.getStatusCodeValue());
        JSONAssert.assertEquals(expectedResponseBody, responseEntity.getBody(), false);
    }

Upvotes: 0

Gurkan İlleez
Gurkan İlleez

Reputation: 1573

HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);

You have sent body as null. Also you can use mockMvc it is better approach then rest template.

User testUser = new User();
testUser.setName("Test User");
HttpEntity<String> httpEntity = new HttpEntity<String>(testUser, headers);

https://howtodoinjava.com/spring-boot2/testing/spring-boot-mockmvc-example/

Upvotes: 1

Related Questions