使用 mockwebserver 的 RetryInterceptor 测试取消连接
RetryInterceptor testing with mockwebserver cancels connection
我有以下设置:spring 使用 okHttp3 客户端启动应用程序。我有一个自定义重试机制,需要在每种情况下重试有限次数的调用。拦截器如下:
spring 开机:2.5.5
okhttp: 4.9.3
@Slf4j
@RequiredArgsConstructor
public class RetryOnFailureInterceptor implements Interceptor {
private final int maxRetryCount;
@Override
public Response intercept(final Chain chain) throws IOException {
final Request request = chain.request();
int tryCount = 0;
Response response = null;
// first call is actual call, following are first retries
while ((response == null || !response.isSuccessful()) && tryCount < this.maxRetryCount) {
tryCount++;
try {
response = chain.proceed(request);
if (response.isSuccessful()) {
return response;
}
// close response before retry
response.close();
log.info("Intercept, request failed, retry_count={}/{} ", tryCount, this.maxRetryCount);
} catch (final IOException ioException) {
log.info("Caught exception with message={}, retry_count={}/{} ",
ioException.getMessage(), tryCount, this.maxRetryCount);
if (response != null && response.body() != null) {
response.close();
}
}
}
// last try should proceed as is
return chain.proceed(request);
}
}
我想通过以下测试来测试拦截器的功能:
private MockWebServer mockWebServer;
@BeforeEach
void setUp() throws IOException {
this.mockWebServer = new MockWebServer();
this.mockWebServer.start(8080);
}
@AfterEach
void tearDown() throws IOException {
this.mockWebServer.shutdown();
}
@Test
void withRetryInterceptorsTest() throws IOException {
final OkHttpClient httpClient = new CustomOkHttpClientBuilder(getHttpSettings())
.withRetryInterceptor(5)
.build(); //custom client builder I made, it sets timeouts and the interceptor. Also it sets okhttpclient.retryOnConnectionFailure(false) to avoid duplicate retry mechanisms. Also enabling it does not fix it.
final MockResponse timeout1 = new MockResponse().setBodyDelay(20, TimeUnit.DAYS).setHeadersDelay(20, TimeUnit.DAYS);
final MockResponse timeout2 = new MockResponse().setSocketPolicy(SocketPolicy.NO_RESPONSE); //another way to timeout
final MockResponse failure = new MockResponse().setResponseCode(400);
final MockResponse success = new MockResponse().setResponseCode(200);
this.mockWebServer.enqueue(timeout1);
this.mockWebServer.enqueue(timeout2);
this.mockWebServer.enqueue(failure);
this.mockWebServer.enqueue(success);
final Request request = new Request.Builder()
.url("http://localhost:8080")
.get()
.build();
final Response response = httpClient.newCall(request).execute();
assertEquals(200, response.code());
}
当我 运行 测试时,会发生这种情况:
21:47:05.337 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Socket closed, retry_count=1/5
21:47:05.341 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Canceled, retry_count=2/5
21:47:05.341 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Canceled, retry_count=3/5
21:47:05.342 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Canceled, retry_count=4/5
21:47:05.342 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Canceled, retry_count=5/5
我想找出问题所在。它不工作是因为模拟网络服务器中发生的事情,还是当连接超时时您无法重试的真正预期行为,因为调用被取消?
我怀疑是mockwebserver的问题,但不知道怎么解决,也不知道问题出在哪里。
这是 MockWebServer 中的一个错误,目前正在调查中:
我有以下设置:spring 使用 okHttp3 客户端启动应用程序。我有一个自定义重试机制,需要在每种情况下重试有限次数的调用。拦截器如下: spring 开机:2.5.5 okhttp: 4.9.3
@Slf4j
@RequiredArgsConstructor
public class RetryOnFailureInterceptor implements Interceptor {
private final int maxRetryCount;
@Override
public Response intercept(final Chain chain) throws IOException {
final Request request = chain.request();
int tryCount = 0;
Response response = null;
// first call is actual call, following are first retries
while ((response == null || !response.isSuccessful()) && tryCount < this.maxRetryCount) {
tryCount++;
try {
response = chain.proceed(request);
if (response.isSuccessful()) {
return response;
}
// close response before retry
response.close();
log.info("Intercept, request failed, retry_count={}/{} ", tryCount, this.maxRetryCount);
} catch (final IOException ioException) {
log.info("Caught exception with message={}, retry_count={}/{} ",
ioException.getMessage(), tryCount, this.maxRetryCount);
if (response != null && response.body() != null) {
response.close();
}
}
}
// last try should proceed as is
return chain.proceed(request);
}
}
我想通过以下测试来测试拦截器的功能:
private MockWebServer mockWebServer;
@BeforeEach
void setUp() throws IOException {
this.mockWebServer = new MockWebServer();
this.mockWebServer.start(8080);
}
@AfterEach
void tearDown() throws IOException {
this.mockWebServer.shutdown();
}
@Test
void withRetryInterceptorsTest() throws IOException {
final OkHttpClient httpClient = new CustomOkHttpClientBuilder(getHttpSettings())
.withRetryInterceptor(5)
.build(); //custom client builder I made, it sets timeouts and the interceptor. Also it sets okhttpclient.retryOnConnectionFailure(false) to avoid duplicate retry mechanisms. Also enabling it does not fix it.
final MockResponse timeout1 = new MockResponse().setBodyDelay(20, TimeUnit.DAYS).setHeadersDelay(20, TimeUnit.DAYS);
final MockResponse timeout2 = new MockResponse().setSocketPolicy(SocketPolicy.NO_RESPONSE); //another way to timeout
final MockResponse failure = new MockResponse().setResponseCode(400);
final MockResponse success = new MockResponse().setResponseCode(200);
this.mockWebServer.enqueue(timeout1);
this.mockWebServer.enqueue(timeout2);
this.mockWebServer.enqueue(failure);
this.mockWebServer.enqueue(success);
final Request request = new Request.Builder()
.url("http://localhost:8080")
.get()
.build();
final Response response = httpClient.newCall(request).execute();
assertEquals(200, response.code());
}
当我 运行 测试时,会发生这种情况:
21:47:05.337 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Socket closed, retry_count=1/5
21:47:05.341 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Canceled, retry_count=2/5
21:47:05.341 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Canceled, retry_count=3/5
21:47:05.342 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Canceled, retry_count=4/5
21:47:05.342 [main] INFO RetryOnFailureInterceptor - Caught exception with message=Canceled, retry_count=5/5
我想找出问题所在。它不工作是因为模拟网络服务器中发生的事情,还是当连接超时时您无法重试的真正预期行为,因为调用被取消?
我怀疑是mockwebserver的问题,但不知道怎么解决,也不知道问题出在哪里。
这是 MockWebServer 中的一个错误,目前正在调查中: