简体   繁体   English

如何使用 TestRestTemplate 集成测试 RESTful APIs PUT 端点?

[英]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 .我目前正在研究Spring Boot CRUD RESTful API ,其User实体由两个参数组成: nameid Its endpoints are:它的端点是:

  • POST REQUEST IN /users - Create an user POST REQUEST IN /users - 创建一个用户
  • GET REQUEST IN /users/{id} - List a specific user by its id GET REQUEST IN /users/{id} - 按 id 列出特定用户
  • GET REQUEST IN /users - List all users GET REQUEST IN /users - 列出所有用户
  • PUT REQUEST IN /users/{id} - Update a specific user by its id PUT REQUEST IN /users/{id} - 通过其 id 更新特定用户
  • DELETE REQUEST IN /users/{id} - Delete a specific user by its id DELETE REQUEST IN /users/{id} - 按 id 删除特定用户

Each endpoint is built with a controller and a service to implement its logic.每个端点都使用 controller 和一个服务来实现其逻辑。

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.不涉及 mocking,所有这一切都将通过使用TestRestTemplate并断言每个操作都正确执行并且每个响应都检查其预期值来完成。

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.如您所见,它缺少 PUT 请求方法测试,即更新端点。 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.如果有人可以帮助解决这个问题,将不胜感激,但没有在网上找到答案。

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

You have sent body as null.您已将正文发送为 null。 Also you can use mockMvc it is better approach then rest template.您也可以使用 mockMvc,它是比 rest 模板更好的方法。

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/ https://howtodoinjava.com/spring-boot2/testing/spring-boot-mockmvc-example/

So, the solution to my problem really was that I was sending a null request body in my httpEntity.所以,我的问题的解决方案实际上是我在我的 httpEntity 中发送了一个 null 请求正文。

I also needed to set the content type to JSON:我还需要将内容类型设置为 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);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM