You need to enable JavaScript to run this app. 如何用MockWebServer触发Retrofit中body().string()的IOException
优惠活动
大模型
产品
解决方案
定价
更多

如何用MockWebServer触发Retrofit中body().string()的IOException

问题原因分析

你之前使用SocketPolicy.DISCONNECT_DURING_RESPONSE_BODY无法达成预期效果的核心原因是异常触发时机不匹配:

  • 该Socket策略的执行逻辑是:MockWebServer写完所有响应头内容后,立刻断开socket连接
  • 此时OkHttp的HTTP层在完成响应头解析、将Response对象封装为Retrofit回调参数之前,就会感知到连接断开,直接把异常抛到Call执行层,触发onFailure回调,根本不会进入你写的onResponse方法内部的try-catch逻辑。
正确实现方式

要达成预期效果,核心要控制两个关键时机:

  • 服务端必须完整推送所有200状态的响应头到客户端,让OkHttp成功解析响应、触发onResponse回调,绝对不能在响应头传输阶段断开连接
  • 必须等业务代码进入onResponse方法、执行到response.body().string()的读取逻辑时,才抛出IOException

可落地的实现代码

不用内置的DISCONNECT类SocketPolicy,通过自定义响应体的写入逻辑精准控制异常触发时机:

MockResponse mockResponse = new MockResponse()
    .setResponseCode(200)
    .setHeader("Content-Type", "application/json")
    .setBody(new ResponseBody() {
        @Override public MediaType contentType() {
            return MediaType.get("application/json");
        }
        @Override public long contentLength() {
            return -1;
        }
        @Override public void writeTo(BufferedSink sink) throws IOException {
            // 先把缓冲区里的响应头内容全部推给客户端,确保客户端能完整接收响应头、触发onResponse回调
            sink.flush();
            // 短暂等待,保证客户端完成onResponse的调用流程,进入body读取逻辑
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new IOException("模拟连接中断", e);
            }
            // 此时再抛出IO异常,会在response.body().string()的调用过程中触发
            throw new IOException("模拟读取响应体时的连接断开");
        }
    });

注意:Thread.sleep的等待时长可以根据实际测试环境调整,只要保证客户端已经收到完整响应头、并触发onResponse回调即可,避免等待时间过短导致异常还是在回调流程之前抛出。

流程验证

按照这个配置执行时:

  • OkHttp收到完整的响应头后,会正常创建Response对象并触发onResponse,不会进入onFailure
  • 业务代码判断response.isSuccessful()为true,调用response.body().string()时,才会读取自定义响应体的内容,此时抛出的IOException会被onResponse内部的catch块捕获,完全符合测试预期。

内容的提问来源于stack exchange,提问作者CaHa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.02 21:27:03