Java SpringBoot:如何为DeleteREST模板编写单元测试用例

Java SpringBoot:如何为DeleteREST模板编写单元测试用例,java,spring-boot,unit-testing,junit,resttemplate,Java,Spring Boot,Unit Testing,Junit,Resttemplate,我正在尝试为HttpHandler类编写单元测试用例,该类具有用于删除的rest模板调用。为了测试HttpHandler类中sendDelete的功能,我编写了一个usercontroller类来进行resttemplate调用。有人能帮我理解在HtttpHandler类中为sendDelete方法编写单元测试用例的正确方法吗 我有一个类HttpHandler。它有一个函数sendDelete,在该函数中调用restemplate.exchange方法 @Service public class

我正在尝试为HttpHandler类编写单元测试用例,该类具有用于删除的rest模板调用。为了测试HttpHandler类中
sendDelete
的功能,我编写了一个usercontroller类来进行resttemplate调用。有人能帮我理解在
HtttpHandler
类中为
sendDelete
方法编写单元测试用例的正确方法吗

我有一个类HttpHandler。它有一个函数
sendDelete
,在该函数中调用
restemplate.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;
    }
}
@服务
公共类HttpHandler{
公共响应属性sendDelete(字符串url、HttpHeaders、HttpHeaders、R请求主体、类responseClass){
//创建rest模板的实例
RestTemplate RestTemplate=新RestTemplate();
HttpEntity=新的HttpEntity(请求主体,HttpHeader);
info(“删除对“+url+”的请求,正文为:“+JsonUtil.jsoniceExcludeNulls(requestBody));
//发出带有标题的HTTP删除请求
ResponseEntity response=restemplate.exchange(url,HttpMethod.DELETE,entity,Void.class);
info(“删除”+url+:“+JsonUtil.jsonize(响应));
返回响应;
}
}
我正在使用junit5。下面是上述类中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());
    }

@LocalServerPort
专用int端口;
私有字符串baseUrl;
@自动连线
私有HttpHandler HttpHandler;
@之前
public void setBaseUrl(){
this.baseUrl=”http://localhost:“+端口+”/用户”;
}
@试验
public void testSuccessDeleteUserById()引发异常{
this.baseUrl=baseUrl+“/1”;
//创建标题
HttpHeaders HttpHeaders=新的HttpHeaders();
//设置内容类型
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
//发出带有标题的HTTP删除请求
ResponseEntity 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);
    }
}
@RestController
公共类用户控制器{
@删除映射(“/users/{userId}”)
公共响应属性deleteUser(@PathVariable(“userId”)int userId){
返回新的ResponseEntity(未找到HttpStatus.NOT_);
}
}

谢谢你抽出时间

有两种方法

  • 模仿REST模板。要做到这一点,首先,您必须使RestTemplate成为一个字段,并通过构造函数(或任何其他方式)注入它。这允许您注入模拟对象。然后,剩下的就是简单的嘲弄

  • 你可以用。这样,您就不需要更改任何内容。它只是您的方法将请求发送到的web服务器。方法调用完成后,您可以访问记录的请求并进行一些验证

  • 这里有一个粗略的例子。如果要进行大量测试,则可以将web服务器初始化移动到每个方法之前的
    @和每个
    方法之后的
    @中

    公共类HttpHandlerTest{
    私有最终HttpHandler=新HttpHandler();
    @试验
    @鬼鬼祟祟
    公共void testDelete(){
    MockWebServer MockWebServer=新建MockWebServer();
    mockWebServer.start(9889);
    mockWebServer.enqueue(
    新建MockResponse().setResponseCode(200)
    );
    字符串url=”http://localhost:9889";
    Hello Hello=新Hello(“Hello world”);
    final ResponseEntity=handler.sendDelete(url,null,hello,hello.class);
    assertNotNull(实体);
    assertEquals(200,entity.getStatusCode().value());
    final RecordedRequest RecordedRequest=mockWebServer.takeRequest();
    assertEquals(“删除”,recordedRequest.getMethod());
    mockWebServer.close();
    }
    }
    //只是一个用作有效负载的示例类
    同学们好{
    字符串文本;
    公众你好{
    }
    公共Hello(字符串文本){
    this.text=文本;
    }
    公共字符串getText(){
    返回文本;
    }
    公共void setText(字符串文本){
    this.text=文本;
    }
    }
    

    注意。尽管您不会选择第一个解决方案,但我建议您放弃为每个请求初始化RestTemplate。您最好改用WebClient。如果这样做,第一种解决方案将不再有效,而第二种解决方案将保持不变。

    有两种方法可以做到这一点

  • 模仿REST模板。要做到这一点,首先,您必须使RestTemplate成为一个字段,并通过构造函数(或任何其他方式)注入它。这允许您注入模拟对象。然后,剩下的就是简单的嘲弄

  • 你可以用。这样,您就不需要更改任何内容。它只是您的方法将请求发送到的web服务器。方法调用完成后,您可以访问记录的请求并进行一些验证

  • 这里有一个粗略的例子。如果要进行大量测试,则可以将web服务器初始化移动到每个
    方法之前的
    @和每个
    方法之后的
    @中

    公共类HttpHandlerTest{
    私有最终HttpHandler=新HttpHandler();
    @试验
    @鬼鬼祟祟
    公共void testDelete(){
    MockWebServer MockWebServer=新建MockWebServer();
    mockWebServer.start(9889);
    mockWebServer.enqueue(
    新建MockResponse().setResponseCode(200)
    );
    字符串url=”http://localhost:9889";
    Hello Hello=新Hello(“Hello world”);
    final ResponseEntity=handler.sendDelete(url,null,hello,hello.class);
    assertNotNull(实体);
    assertEquals(200,entity.getStatusCode().value());
    最终记录