英文:
Spring boot : How to write unit test case for delete rest template
问题
以下是您提供的内容的翻译部分:
我正在尝试为 HttpHandler 类编写单元测试用例,该类在其中调用了删除的 rest template 调用。我已经创建了一个 usercontroller 类,以便在其中进行 resttemplate 调用,以测试 HttpHandler 类中 sendDelete
方法的功能。有人可以帮助我理解如何正确编写 HtttpHandler
类中 sendDelete
方法的单元测试用例吗?
我有一个名为 HttpHandler 的类。它有一个名为 sendDelete
的函数,在其中调用了 resttemplate.exchange
方法。
@Service
public class HttpHandler {
public <T, R> ResponseEntity<Void> sendDelete(String url, HttpHeaders httpHeaders, R requestBody, Class<T> responseClass) {
// 创建 rest template 实例
RestTemplate restTemplate = new RestTemplate();
HttpEntity<R> entity = new HttpEntity<R>(requestBody, httpHeaders);
logger.info("DELETE 请求至 " + url + ",使用 body: " + JsonUtil.jsonizeExcludeNulls(requestBody));
// 使用 headers 发起 HTTP DELETE 请求
ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.DELETE, entity, Void.class);
logger.info("DELETE " + url + ":" + JsonUtil.jsonize(response));
return response;
}
}
我正在使用 JUnit 5。以下是上述类中 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";
// 创建 headers
HttpHeaders httpHeaders = new HttpHeaders();
// 设置内容类型
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
// 使用 headers 发起 HTTP DELETE 请求
ResponseEntity<Void> actual = httpHandler.sendDelete(baseUrl, httpHeaders, null, Void.class);
assertEquals(404, actual.getStatusCodeValue());
}
以下是用户控制器类:
@RestController
public class UserController {
@DeleteMapping("/users/{userId}")
public ResponseEntity<Void> deleteUser(@PathVariable("userId") int userId){
return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
}
}
谢谢您的时间!
英文:
I'm trying to write unit test case for HttpHandler class which has rest template call for delete. I've crated a usercontroller class to make resttemplate call in order to test the functionality of sendDelete
in HttpHandler class. Can someone help me too understand what is the correct way to write unit test case for sendDelete
method in HtttpHandler
class?
I have a class HttpHandler. It has a function sendDelete
where it calls resttemplate.exchange
method
@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;
}
}
I'm using junit5. Below is the unit test case for sendDelete method in above class:
@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());
}
Below is the user controller class
@RestController
public class UserController {
@DeleteMapping("/users/{userId}")
public ResponseEntity<Void> deleteUser(@PathVariable("userId") int userId){
return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
}
}
Thank you for your time!
答案1
得分: 0
以下是翻译好的部分:
-
Mocking RestTemplate. 要做到这一点,首先,您必须将 RestTemplate 设置为一个字段,并通过构造函数(或任何其他方式)注入它。这允许您注入一个模拟对象。然后,其余部分就是简单的模拟。
-
您可以使用 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();
}
}
// 仅供使用作为有效载荷的示例类
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。如果这样做,第一种解决方案将不再起作用,而第二种解决方案将保持不变。
英文:
There are two ways to do it.
-
Mocking RestTemplate. To do it, first, you have to make the RestTemplate a field, and inject it through the constructor (or any other way). This allows you to inject a mock object. Then, the rest is plain and simple mocking.
-
You can use MockWebServer. This way you do not need to change anything. It is just a web server that your method will send the request to. After the method call finishes, you can access the recorded request and make some validations.
Here's a crude example. If you will have a lot of those tests, then you can move the web server initialization to a @BeforeEach
method and the destroying to @AfterEach
method.
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;
}
}
Note. Even though you will not opt for the first solution, I recommend you do abandon initializing RestTemplate for each request. You better use WebClient instead. If you do so, the first solution will not work anymore, while the second will remain intact.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论