gpt4 book ai didi

java - 在单元测试中模拟 RestTemplate#postForObject

转载 作者:行者123 更新时间:2023-12-02 02:09:25 26 4
gpt4 key购买 nike

给定一个类 EncoderService ,它具有以下 createNewStream 方法以及该方法中使用的一堆常量,我如何使用 mockito 来为 createNewStream 方法编写单元测试:

public ResponseEntity<Object> createNewStream(Long channelId) {
String url = IP + VERSION + serverName + VHOSTS + vhostName + APP_NAME + appName + STREAM_FILES;

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON_UTF8));
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.setAcceptCharset(Arrays.asList(Charset.forName(UTF_8)));

RestTemplate restTemplate = new RestTemplate();

String udp = "udp://" + "localhost" + ":" + "1935";
Map<String, String> map = new HashMap<>();
map.put("name", STREAMS + appName + channelId);
map.put("serverName", serverName);
map.put("uri", udp);
HttpEntity<Map<String, String>> request = new HttpEntity<>(map, headers);

HttpStatus statusCode = null;
try {
ResponseEntity<Object> response = restTemplate.postForEntity(url, request, Object.class);
statusCode = response.getStatusCode();
map.put(MESSAGE, "successful");
return new ResponseEntity<>(map, statusCode);
} catch (HttpStatusCodeException e) {
map.put(MESSAGE, e.getMessage());
return new ResponseEntity<>(map, HttpStatus.BAD_REQUEST);
}
}

最佳答案

RestTemplate是一个类,而不是一个接口(interface),它实现了实际的 HTTP 传输。两者都阻碍了编写可测试的方法。最重要的是,您正在构造一个对操作系统级别有副作用的类的实例,而不是将其注入(inject),这一事实对这种情况没有帮助。那么解决的方法是:

  • 基于接口(interface)而不是实现来编写方法,RestOperations在这种情况下
  • 注入(inject)一个实现 RestOperations 的实例,例如RestTemplate 的一个实例对于生产,通过构造函数参数(首选)、方法参数或通过 Supplier<RestOperations>定义为类上的字段
  • 用测试实现或测试中的模拟替换实际实例。我想选择 Mockito.mock(RestOperations.class) 更容易因为RestOperations就像所有其他 Spring 接口(interface)定义了太多手动编写测试实现的方法

所以在 EncoderService你可以拥有:

private final RestOperations restClient;

public EncoderService(RestOperations restClient) {
this.restClient = restClient;
}

public ResponseEntity<Object> createNewStream(Long channelId) {
...
ResponseEntity<Object> response = restClient.postForEntity(...
...
}

然后在 EncoderServiceTest :

ResponseEntity<Object> expectedReturnValue = ...

RestOperations testClient = mock(RestOperations.class);
doReturn(expectedReturnValue).when(testClient).postForEntity(any(), any(), anyClass());

EncoderService service = new EncoderService(testClient);
// use the service

对于其他两种情况,测试设置完全相同,只是您将实例而不是构造函数传递到方法调用中,或者覆盖EncoderService上的供应商。实例返回 testClient .

我已经回答了一个关于 ProcessBuilder 的非常类似的问题它对操作系统级别也有副作用,并且是直接在此处测试的方法中构建的 Error trying to mock constructor for ProcessBuilder using PowerMockito您可以应用完全相同的策略。

关于java - 在单元测试中模拟 RestTemplate#postForObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50245444/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com