繁体   English   中英

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

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

我目前正在研究Spring Boot CRUD RESTful API ,其User实体由两个参数组成: nameid 它的端点是:

  • POST REQUEST IN /users - 创建一个用户
  • GET REQUEST IN /users/{id} - 按 id 列出特定用户
  • GET REQUEST IN /users - 列出所有用户
  • PUT REQUEST IN /users/{id} - 通过其 id 更新特定用户
  • DELETE REQUEST IN /users/{id} - 按 id 删除特定用户

每个端点都使用 controller 和一个服务来实现其逻辑。

我已经为我的控制器和服务编写了单元测试,现在我正在尝试构建集成测试来断言我的端点作为一组组件正常工作。

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

以下是我已经构建的测试:

@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;
    }
}

如您所见,它缺少 PUT 请求方法测试,即更新端点。 为了实现它的逻辑,我需要发送一个包含将覆盖旧用户特征的内容的消息正文,但是如何?

这是我到目前为止所做的:

    @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);
    }
    

如果有人可以帮助解决这个问题,将不胜感激,但没有在网上找到答案。

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

您已将正文发送为 null。 您也可以使用 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/

所以,我的问题的解决方案实际上是我在我的 httpEntity 中发送了一个 null 请求正文。

我还需要将内容类型设置为 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