Spring boot:RestTemplate POST 调用不返回创建的状态码
Posted
技术标签:
【中文标题】Spring boot:RestTemplate POST 调用不返回创建的状态码【英文标题】:Spring boot : RestTemplate POST call does not return created status code 【发布时间】:2020-11-20 03:18:27 【问题描述】:我是 Spring Boot Rest 模板的新手。我正在尝试为休息模板发布调用编写单元测试用例。 我创建了一个用户控制器来发送虚拟数据。 为 POST 调用编写的用户控制器对单元测试是否正确?如果不是,那么正确的写法是什么?我从用户控制器返回的响应是否正确?我应该将状态码返回为 200 还是 201? 有人可以帮我吗?
下面是用户控制器
@PostMapping("/users")
public User createUser(@RequestBody User user)
List<String> messages = new ArrayList<>();
messages.add("Hi");
User createUser = new User();
createUser.setId(1);
createUser.setName("John");
createUser.setAge(22);
createUser.setMessages(messages);
return user;
下面是调用后的单元测试用例:
@Test
public void testSuccessPostUser() throws Exception
String baseUrl = "http://localhost:8080/users";
List<String> messages = new ArrayList<>();
messages.add("Hi");
User user = new User();
user.setId(1);
user.setName("John");
user.setAge(22);
user.setMessages(messages);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity<User> httpEntity = new HttpEntity<>(user, httpHeaders);
HttpHandler httpHandler = new HttpHandler();
ResponseEntity<User> actual = httpHandler.sendPost(baseUrl, httpHeaders, user, User.class);
//verify request succeed
assertEquals(HttpStatus.CREATED, actual.getStatusCode());
assertEquals(201, actual.getStatusCodeValue());
assertTrue(responseBody.contains(id);
【问题讨论】:
【参考方案1】:首先,为了测试HTTP控制器你可以使用MockMvc
。
示例测试:
mockMvc.perform(post("/users")
.contentType(MediaType.APPLICATION_JSON)
.content(" "id": 1, "Name": "John", "Age": 22 ")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.id").value($id))
.andExpect(jsonPath("$.value").value("some-value"));
更多详情docs
要返回 201 代码,您需要在控制器中添加 @ResponseStatus(HttpStatus.CREATED)
。
【讨论】:
如果我错了请纠正我,我们不使用mockMvc进行集成测试吗? 是的,这是正确的,但我认为你的情况是集成测试:) 我正在编写单元测试。正确的写法是什么? 您调用端点http://localhost:8080/users
,如果它没有存根,您的测试类型是集成。 MockMvc
提供了一个优雅且易于使用的 API 来调用 Web 端点并同时检查和断言它们的响应。您必须添加 @ContextConfiguration
和 @WebAppConfiguration
来测试以准备用于测试的 Spring 上下文。
我正在使用junit5编写单元测试用例。我正在使用@SpringBootTest
注释。我还需要@contextConfiguration
和@WebAppConfiguration
吗?另外,当您说为测试准备 spring 上下文时,它到底是什么意思?【参考方案2】:
如果你想返回自定义状态码,你应该返回RepsponseEntity
:
@PostMapping("/users")
public ResposneEntity<User> createUser(@RequestBody User user)
...
return new ResponseEntity(user, HttpStatus.CREATED);
如果您想了解 POST 方法的正确 https 状态,我建议您阅读以下内容:What status code should we return if the POST succeeds but does not result in creating anything new?
【讨论】:
【参考方案3】:POST 默认返回 200。
如果你想让它返回 201,添加这个:
@ResponseStatus(HttpStatus.CREATED)
@PostMapping("/users")
public User createUser(@RequestBody User user)
【讨论】:
以上是关于Spring boot:RestTemplate POST 调用不返回创建的状态码的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Java Spring boot 中模拟 RestTemplate?
使用注入 java 和 spring boot 的 RestTemplate 类进行单元测试
spring-boot Autowired DiscoveryClient RestTemplate UnknownHostException