[英]Mock of RestTemplate in Junit test for mockRestTemplate.postForObject() return null
[英]Mocking RestTemplate#postForObject in a unit test
给定一个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
是一个类,而不是一个接口,它实现了实际的HTTP传输。 两者都妨碍编写可测试的方法。 最重要的是,您正在构造对OS级别具有副作用而不是注入它的类的实例并不能解决问题。 因此,解决方法是:
RestOperations
Supplier<RestOperations>
注入实现RestOperations
的实例,例如用于生产的RestTemplate
实例 Mockito.mock(RestOperations.class)
比较容易,因为像所有其他Spring接口一样, RestOperations
定义了太多方法来手动编写测试实现 因此,在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
的非常相似的问题,该问题在操作系统级别上也有副作用,并且是直接在此处测试的方法中构造的。尝试使用PowerMockito模拟ProcessBuilder的构造函数时出错您可以应用完全相同的策略。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.