我如何对这段代码进行单元测试?
private ODataQueryResult buildAndExecuteQuery(String path String entity,
String sapClient, String sapLanguage) {
ODataQuery query = ODataQueryBuilder
.withEntity(path, entity)
.withHeader("sap-client", sapClient, true)
.withHeader("sap-language", sapLanguage, true)
.withoutMetadata()
.build();
return query.execute();
}更准确地说:我如何验证我的代码调用了所有正确的函数,例如,不会忘记调用withoutMetadata或设置所需的头文件?
不幸的是,ODataQueryBuilder和ODataQuery是类,而不是接口。这使得模仿变得很棘手。ODataQueryBuilder甚至是final,完全禁用了模仿。此外,该链以静态方法withEntity开始,该方法也不能被模仿。
是否有帮助程序允许我监视行为或模拟数据,类似于https://blogs.sap.com/2017/09/19/step-12-with-sap-s4hana-cloud-sdk-automated-testing/中描述的MockUtil
发布于 2019-09-14 21:01:31
您说得对,这些类的结构使它们很难模仿,但由于它们是"SAP Cloud Platform SDK for Service Development“的一部分,我们无法更改它们。
其他方法可能是:
我们在SAP Cloud SDK中使用WireMock,并通过testutil-core模块中包含的MockUtil提供一些集成到我们的SDK中。
我希望这会有一点帮助!
发布于 2019-09-16 21:26:56
部分解决方案是在模拟HttpClient上模拟执行ODataQuery。
首先,需要将原始方法分成两个独立的部分,一个用于构建查询,另一个用于执行查询。无论如何,这是一个很好的设计,所以没什么大问题:
private ODataQuery buildQuery(String path, String entity,
String sapClient, String sapLanguage) {
return ODataQueryBuilder
.withEntity(path, entity)
.withHeader("sap-client", sapClient, true)
.withHeader("sap-language", sapLanguage, true)
.withoutMetadata()
.build();
}
private ODataResponse executeQuery(ODataQuery query) {
return query.execute();
}现在可以按如下方式测试buildQuery方法:
@Test
public void addsSapLanguageToHeader() throws ODataException, IOException {
ODataQuery query = cut.buildQuery("api/v2", "business-partners", "", "fr");
HttpUriRequest request = getRequest(query);
assertContainsHeader(request, "sap-language", "fr");
}getRequest方法生成一个假的HttpClient,它存根了让query.execute(httpClient)正常工作所需的所有方法。它存储实际的请求,并将其返回以供进一步检查。使用Mockito的示例实现:
private HttpUriRequest getRequest(ODataQuery query) throws ODataException, IOException {
// stub methods to make code work
HttpResponse response = mock(HttpResponse.class);
when(httpClient.execute(any())).thenReturn(response);
StatusLine statusLine = mock(StatusLine.class);
when(response.getStatusLine()).thenReturn(statusLine);
HttpEntity entity = mock(HttpEntity.class);
when(response.getEntity()).thenReturn(entity);
InputStream inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
when(entity.getContent()).thenReturn(inputStream);
Header[] headers = new Header[0];
when(response.getAllHeaders()).thenReturn(headers);
// simulate the execution of the query
query.execute(httpClient);
// grab the original argument from the mock for inspection
ArgumentCaptor<HttpUriRequest> captor = ArgumentCaptor.forClass(HttpUriRequest.class);
verify(httpClient).execute(captor.capture());
HttpUriRequest request = captor.getValue();
return request;
}当然,这个解决方案远非完美。
首先,仅使此测试工作所需的代码量就表明,随着时间的推移,此测试将变得多么脆弱。每当CloudSDK决定向调用序列添加方法或验证时,此测试都会中断。还要注意的是,通过测试private方法,测试是有侵入性的,而黄金标准说我们应该只测试public方法。
其次,executeQuery方法仍然无法测试。执行路径也不同,因为测试代码使用.execute(httpClient)变量来运行查询,而原始代码使用.execute(destinationName)变量。两者碰巧共享代码,但这种情况可能会随着时间的推移而改变。
https://stackoverflow.com/questions/57919825
复制相似问题