【发布时间】:2021-10-24 00:18:16
【问题描述】:
我正在尝试在 OkHttpClient 抛出 IOException 的情况下测试我的代码库
正在测试的代码
try (var response = okHttpClient.newCall(request).execute()) {
return response;
} catch (final IOException e) {
log.error("IO Error from API", e);
throw new ApiException(e.getMessage(), e);
}
测试
@Test
void createCustomer_WhenValidRequestAndIOException_ThenThrowAPIException() throws ZeusServiceException, ZeusClientException {
//Given
final OkHttpClient okHttpClientMock = mock(OkHttpClient.class, RETURNS_DEEP_STUBS);
final OkHttpClient.Builder okHttpBuilderMock = mock(OkHttpClient.Builder.class);
httpClient = new HttpClient(okHttpClientMock, configuration, objectMapper);
//When
when(okHttpClientMock.newBuilder()).thenReturn(okHttpBuilderMock);
when(okHttpBuilderMock.build()).thenReturn(okHttpClientMock);
when(okHttpClientMock.newCall(any())).thenThrow(IOException.class);
final var result = httpClient.createCustomer(request);
assertThatThrownBy(() -> httpClient.createCustomer(request))
.isInstanceOf(ApiException.class)
.hasMessage("IO Error from API");
}
我试图模拟 OkHttpClient 和 Builder 类,但是 Builder 是最终的,mockito 无法模拟它。
在被测类的构造函数中,建议通过调用 this 来创建 OkHttpClient 的新实例
this.okHttpClient = okHttpClient.newBuilder().build();
我尝试围绕 OkHttpClient 创建一个包装器,但这也不起作用
public class OkHttpClientWrapper extends OkHttpClient {
private OkHttpClient okHttpClient;
public OkHttpClientWrapper(final OkHttpClient okHttpClient) {
this.okHttpClient = okHttpClient;
}
@Override
public OkHttpClient.Builder newBuilder() {
return new Builder(okHttpClient);
}
}
}
如何强制 okhttpclient 抛出 IOException?
【问题讨论】:
-
你有没有研究过 PowerMockito 来模拟最终课程?
-
是的,但人们说 PowerMockito 是邪恶的stackoverflow.com/questions/30162200/why-not-powermock
-
也许为
OkHttpClient创建一个Factory,然后模拟Factory? -
尽管 PowerMock 是 是邪恶的,并且 2021 年对单元测试 RESTful 端点的回答是改用 github.com/square/okhttp/tree/master/mockwebserver 之类的东西,但这并没有改变这一事实。跨度>
-
@GhostCat 确实在 MockWebServer 中有一种方法可以模拟关闭/终止的连接,它涵盖了测试场景。请查看提交的答案