java - 为具有不带参数的方法的接口编写单元测试用例
问题描述
我有一个接口,它有一个没有参数的方法
public interface HealthStatus {
Integer healthCheck();
}�
实现如下
@Override
public Integer healthCheck() {
Integer status = 0;
try {
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
if (proxyConfigProperties.getEnabled()) {
Proxy proxy = new Proxy(java.net.Proxy.Type.HTTP, new InetSocketAddress(proxyConfigProperties.getUrl(), proxyConfigProperties.getPort()));
simpleClientHttpRequestFactory.setProxy(proxy);
}
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(simpleClientHttpRequestFactory));
ResponseEntity<String> healthResponse = restTemplate.exchange(eVerifyGovernmentProperties.getUrl(), HttpMethod.GET, null, String.class);
status = (healthResponse.getStatusCode() == HttpStatus.OK) ? 200 : 202;
} catch (Throwable th) {
th.printStackTrace();
}
return status;
}�
我如何针对正面场景和负面场景对该方法进行单元测试。
编辑:
我已经重构了我的类如下
@Service
@Qualifier("implementation")
public class HealthStatusImpl implements HealthStatus {
@Autowired
RestTemplateConfig restTemplateConfig;
@Autowired
private EVerifyGovernmentProperties eVerifyGovernmentProperties;
@Override
public Integer healthCheck() {
Integer status = 0;
try {
ResponseEntity<String> healthResponse = restTemplateConfig.getRestTemplate().exchange(eVerifyGovernmentProperties.getUrl(), HttpMethod.GET, null, String.class);
status = (healthResponse.getStatusCode() == HttpStatus.OK) ? 200 : 202;
} catch (Throwable th) {
th.printStackTrace();
}
return status;
}
}
这是实例化 RestTemplate 的类
@Component
public class RestTemplateConfig {
@Autowired
ProxyConfigProperties proxyConfigProperties;
public RestTemplate getRestTemplate(){
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
if (proxyConfigProperties.getEnabled()) {
Proxy proxy = new Proxy(java.net.Proxy.Type.HTTP, new InetSocketAddress(proxyConfigProperties.getUrl(), proxyConfigProperties.getPort()));
simpleClientHttpRequestFactory.setProxy(proxy);
}
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(simpleClientHttpRequestFactory));
return restTemplate;
}
}
解决方案
实际上,这就是您要模拟的内容:
restTemplateConfig.getRestTemplate().exchange(eVerifyGovernmentProperties.getUrl(), HttpMethod.GET, null, String.class);
但这将需要深度模拟,这也是一种不好的气味:您不需要定义这样的语句来调用其余模板。这个责任应该在一个特定的类中定义。
因此,例如,将它移动到特定 bean 的方法中,RestTemplateService
这将使您免于传递尽可能多的参数,并且还可以通过减少其依赖关系来平衡该类的更好责任:
ResponseEntity<String> healthResponse = restTemplateService.getForHealthCheck();
现在只需用 Mockito 模拟它。
关于RestTemplateService
,您可以创建自己的类或依赖 Feign(这里Spring Feign更有意义)通过接口启用声明式休息客户端。
它会给:
public class HealthStatusImpl implements HealthStatus {
private RestTemplateService restTemplateService;
// favor constructor injection
public HealthStatusImpl(RestTemplateService restTemplateService){
this.restTemplateService = restTemplateService;
}
@Override
public Integer healthCheck() {
Integer status = 0;
try {
ResponseEntity<String> healthResponse = restTemplateService.getForHealthCheck();
status = healthResponse.getStatusCode().is2xxSuccessful() ? 200 : 400;
} catch (Throwable th) {
th.printStackTrace();
}
return status;
}
}
请注意,这 Status.is2xxSuccessful()
通常会更好,因为它对任何成功的响应( 、 等)都返回200
true 201
。如果它不成功,你想返回一个错误响应代码。
在单元测试方面,您应该模拟此依赖项并根据您的场景记录模拟行为。
请注意,在您的情况下,您不想加载整个 spring 上下文,但您想执行一个普通的单元测试,即没有容器。所以不要@SpringBootTest
只使用 JUnit 和 Mockito。
例如 JUnit 5 :
@ExtendWith(MockitoExtension.class)
public class HealthStatusImplTest{
private HealthStatusImpl healthStatusImpl;
@Mock
private RestTemplateService restTemplateServiceMock;
@BeforeEach
public void beforeEach(){
healthStatusImpl = new HealthStatusImpl(restTemplateService);
}
@Test
public void healthCheck_when_200_is_returned(){
Mockito.when(restTemplateServiceMock)
.getForHealthCheck().thenReturn(new ResponseEntity(HttpStatus.OK));
assertEquals(200, healthStatusImpl.healthCheck());
}
@Test
public void healthCheck_when_200_is_not_returned(){
Mockito.when(restTemplateServiceMock)
.getForHealthCheck().thenReturn(new ResponseEntity(HttpStatus.NOT_FOUND));
assertEquals(400, healthStatusImpl.healthCheck());
}
}
当然,RestTemplateService
也应该是单一测试,而单一测试并不能减轻为更高级别组件编写集成测试的负担。
推荐阅读
- python - 使变量成为列表的名称?Python
- postgresql - 想知道postgresql连接的原因
- java - Gson - 如何进行特殊处理,如掩蔽
- sequelize.js - 如何使用存储在变量中的值进行 RAW 查询
- google-bigquery - 带有“更新”标志的数据流管道因“Reshuffle/GroupByKey”错误而失败
- makefile - 查找哪个makefile在包含的make中设置了一个变量
- python - TensorFlow 训练对象检测模型
- unity3d - 碰撞系统不工作。没有错误,只是不会记录弹丸击中玩家
- android - Android 促销启动后临时密码发放无法正常工作
- swift - 如何在 Swift 中初始化结构或类?