Spring boot : 如何编写用于删除 rest 模板的单元测试用例
Spring boot : How to write unit test case for delete rest template
我正在尝试为 HttpHandler class 编写单元测试用例,它具有用于删除的其余模板调用。为了测试 HttpHandler class 中 sendDelete
的功能,我创建了一个用户控制器 class 来进行 resttemplate 调用。有人可以帮我理解在 HtttpHandler
class 中为 sendDelete
方法编写单元测试用例的正确方法是什么?
我有一个 class HttpHandler。它有一个函数 sendDelete
调用 resttemplate.exchange
方法
@Service
public class HttpHandler {
public <T,R> ResponseEntity<Void> sendDelete(String url, HttpHeaders httpHeaders, R requestBody, Class<T> responseClass) {
//create an instance of rest template
RestTemplate restTemplate = new RestTemplate();
HttpEntity<R> entity = new HttpEntity<R>(requestBody, httpHeaders);
logger.info("DELETE request to " + url + " with body: " + JsonUtil.jsonizeExcludeNulls(requestBody));
//make an HTTP DELETE request with headers
ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.DELETE, entity, Void.class);
logger.info("DELETE" + url + ": " + JsonUtil.jsonize(response));
return response;
}
}
我正在使用 junit5。下面是上面class:
中sendDelete方法的单元测试用例
@LocalServerPort
private int port;
private String baseUrl;
@Autowired
private HttpHandler httpHandler;
@BeforeEach
public void setBaseUrl(){
this.baseUrl = "http://localhost:"+ port + "/users";
}
@Test
public void testSuccessDeleteUserById() throws Exception{
this.baseUrl = baseUrl + "/1";
//create headers
HttpHeaders httpHeaders = new HttpHeaders();
//set content type
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
//make an HTTP DELETE request with headers
ResponseEntity<Void> actual = httpHandler.sendDelete(baseUrl, httpHeaders, null, Void.class);
assertEquals(404, actual.getStatusCodeValue());
}
下面是用户控制器class
@RestController
public class UserController {
@DeleteMapping("/users/{userId}")
public ResponseEntity<Void> deleteUser(@PathVariable("userId") int userId){
return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
}
}
感谢您的宝贵时间!
有两种方法。
模拟 RestTemplate。为此,首先,您必须使 RestTemplate 成为一个字段,并通过构造函数(或任何其他方式)注入它。这允许您注入模拟对象。然后,剩下的就是简单明了的mocking了。
可以使用MockWebServer。这样你就不需要改变任何东西。它只是一个 Web 服务器,您的方法将向其发送请求。方法调用完成后,您可以访问记录的请求并进行一些验证。
这是一个粗略的例子。如果你有很多这样的测试,那么你可以将 Web 服务器初始化移动到 @BeforeEach
方法,并将销毁移动到 @AfterEach
方法。
public class HttpHandlerTest {
private final HttpHandler handler = new HttpHandler();
@Test
@SneakyThrows
public void testDelete() {
MockWebServer mockWebServer = new MockWebServer();
mockWebServer.start(9889);
mockWebServer.enqueue(
new MockResponse().setResponseCode(200)
);
String url = "http://localhost:9889";
Hello hello = new Hello("hello world");
final ResponseEntity<Void> entity = handler.sendDelete(url, null, hello, Hello.class);
assertNotNull(entity);
assertEquals(200, entity.getStatusCode().value());
final RecordedRequest recordedRequest = mockWebServer.takeRequest();
assertEquals("DELETE", recordedRequest.getMethod());
mockWebServer.close();
}
}
// just an example class to use as a payload
class Hello {
String text;
public Hello() {
}
public Hello(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
注意。即使您不会选择第一种解决方案,我还是建议您放弃为每个请求初始化 RestTemplate。您最好改用 WebClient。如果这样做,第一个解决方案将不再有效,而第二个将保持不变。
我正在尝试为 HttpHandler class 编写单元测试用例,它具有用于删除的其余模板调用。为了测试 HttpHandler class 中 sendDelete
的功能,我创建了一个用户控制器 class 来进行 resttemplate 调用。有人可以帮我理解在 HtttpHandler
class 中为 sendDelete
方法编写单元测试用例的正确方法是什么?
我有一个 class HttpHandler。它有一个函数 sendDelete
调用 resttemplate.exchange
方法
@Service
public class HttpHandler {
public <T,R> ResponseEntity<Void> sendDelete(String url, HttpHeaders httpHeaders, R requestBody, Class<T> responseClass) {
//create an instance of rest template
RestTemplate restTemplate = new RestTemplate();
HttpEntity<R> entity = new HttpEntity<R>(requestBody, httpHeaders);
logger.info("DELETE request to " + url + " with body: " + JsonUtil.jsonizeExcludeNulls(requestBody));
//make an HTTP DELETE request with headers
ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.DELETE, entity, Void.class);
logger.info("DELETE" + url + ": " + JsonUtil.jsonize(response));
return response;
}
}
我正在使用 junit5。下面是上面class:
中sendDelete方法的单元测试用例@LocalServerPort
private int port;
private String baseUrl;
@Autowired
private HttpHandler httpHandler;
@BeforeEach
public void setBaseUrl(){
this.baseUrl = "http://localhost:"+ port + "/users";
}
@Test
public void testSuccessDeleteUserById() throws Exception{
this.baseUrl = baseUrl + "/1";
//create headers
HttpHeaders httpHeaders = new HttpHeaders();
//set content type
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
//make an HTTP DELETE request with headers
ResponseEntity<Void> actual = httpHandler.sendDelete(baseUrl, httpHeaders, null, Void.class);
assertEquals(404, actual.getStatusCodeValue());
}
下面是用户控制器class
@RestController
public class UserController {
@DeleteMapping("/users/{userId}")
public ResponseEntity<Void> deleteUser(@PathVariable("userId") int userId){
return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
}
}
感谢您的宝贵时间!
有两种方法。
模拟 RestTemplate。为此,首先,您必须使 RestTemplate 成为一个字段,并通过构造函数(或任何其他方式)注入它。这允许您注入模拟对象。然后,剩下的就是简单明了的mocking了。
可以使用MockWebServer。这样你就不需要改变任何东西。它只是一个 Web 服务器,您的方法将向其发送请求。方法调用完成后,您可以访问记录的请求并进行一些验证。
这是一个粗略的例子。如果你有很多这样的测试,那么你可以将 Web 服务器初始化移动到 @BeforeEach
方法,并将销毁移动到 @AfterEach
方法。
public class HttpHandlerTest {
private final HttpHandler handler = new HttpHandler();
@Test
@SneakyThrows
public void testDelete() {
MockWebServer mockWebServer = new MockWebServer();
mockWebServer.start(9889);
mockWebServer.enqueue(
new MockResponse().setResponseCode(200)
);
String url = "http://localhost:9889";
Hello hello = new Hello("hello world");
final ResponseEntity<Void> entity = handler.sendDelete(url, null, hello, Hello.class);
assertNotNull(entity);
assertEquals(200, entity.getStatusCode().value());
final RecordedRequest recordedRequest = mockWebServer.takeRequest();
assertEquals("DELETE", recordedRequest.getMethod());
mockWebServer.close();
}
}
// just an example class to use as a payload
class Hello {
String text;
public Hello() {
}
public Hello(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
注意。即使您不会选择第一种解决方案,我还是建议您放弃为每个请求初始化 RestTemplate。您最好改用 WebClient。如果这样做,第一个解决方案将不再有效,而第二个将保持不变。