OkHttp Mock测试在CI分层中的应用 - 第1节

OkHttp 是什么?先聊聊我的看法

做 Android 开发的朋友,对 OkHttp 应该不陌生。我最早接触它是在 2015 年,那时候项目里还在用 HttpURLConnection,每次写网络请求都挺痛苦的——代码冗余、连接管理得自己搞、遇到重定向还要手动处理。后来换了 OkHttp,说实话,有种“原来网络请求可以这么清爽”的感觉。

OkHttp 是 Square 公司开源的一个 HTTP 客户端。它在 Android 和 Java 圈子里基本是事实标准了。为什么大家愿意用?我总结了几点核心优势。

核心特性一览

特性 说明 我个人觉得最实用的地方
HTTP/2 支持 同一个主机可以复用连接,减少延迟 接口多的页面,加载速度能快一倍
连接池 复用 TCP 连接,减少三次握手开销 频繁请求时特别明显,省流量也省时间
Gzip 压缩 透明处理压缩,减小传输体积 我自己测试过,JSON 数据能压缩 60% 以上
响应缓存 支持 HTTP 缓存策略,避免重复请求 配合得当的话,弱网体验能提升很多
拦截器 请求/响应的拦截与修改 这是我最常用的功能,日志、重试、Mock 都靠它
失败重试 自动处理连接失败时的重试逻辑 注意了,默认是会自动重试的,有些场景要关掉
一点经验: 我第一次用 OkHttp 时,觉得它配置项太多了。其实大部分场景用默认配置就够了。别一上来就想着定制化,先把基础跑通再说。

基本使用:GET 请求怎么做?

先看一个最基础的 GET 请求。我习惯把 OkHttp 客户端做成单例,这样连接池和配置可以复用。

OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .build();

Request request = new Request.Builder()
        .url("https://api.example.com/users")
        .addHeader("Accept", "application/json")
        .build();

// 同步请求(注意:不能在主线程调用)
try {
    Response response = client.newCall(request).execute();
    if (response.isSuccessful()) {
        String body = response.body().string();
        System.out.println("响应数据:" + body);
    }
} catch (IOException e) {
    e.printStackTrace();
}
曾经踩过的坑: 同步请求的 execute() 方法会阻塞当前线程。我在一个老项目里看到有人在主线程直接调用了,结果 ANR 了。一定要放到子线程或者用异步方式。

异步 GET 请求

实际开发中,我更推荐用异步方式。OkHttp 的回调是在子线程执行的,不能直接更新 UI,记得切回主线程。

client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        // 网络错误或者请求取消
        e.printStackTrace();
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (response.isSuccessful()) {
            String body = response.body().string();
            // 这里获取到 body 后,切到主线程更新 UI
        }
    }
});

你想想看,异步请求的好处是什么?不阻塞 UI 线程,用户操作流畅。但要注意一点:response.body().string() 只能调用一次。我刚开始就犯过这个错,第一次打印了日志,后面再取数据就为空了。

基本使用:POST 请求怎么做?

POST 请求稍微复杂一点,主要在于请求体的构建。常用的几种格式我都列出来。

Form 表单提交

RequestBody formBody = new FormBody.Builder()
        .add("username", "admin")
        .add("password", "123456")
        .build();

Request request = new Request.Builder()
        .url("https://api.example.com/login")
        .post(formBody)
        .build();

JSON 数据提交

这是目前最常用的方式。用 MediaType 指定内容类型,然后用 RequestBody 传 JSON 字符串。

MediaType JSON = MediaType.parse("application/json; charset=utf-8");
String json = "{\"name\":\"张三\",\"age\":25}";
RequestBody body = RequestBody.create(JSON, json);

Request request = new Request.Builder()
        .url("https://api.example.com/user")
        .post(body)
        .addHeader("Content-Type", "application/json")
        .build();
我的习惯: 我会把 JSON 的序列化交给 Gson 或 Moshi 处理。接口定义好数据类,直接传对象,代码更干净。手动拼接 JSON 字符串容易出错,我之前调试过一个小时,就只是因为少了个引号。

文件上传

File file = new File("/sdcard/photo.jpg");
RequestBody fileBody = RequestBody.create(
        MediaType.parse("image/jpeg"), file);

MultipartBody body = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("file", "photo.jpg", fileBody)
        .build();

Request request = new Request.Builder()
        .url("https://api.example.com/upload")
        .post(body)
        .build();

OkHttp 的整体结构

为了帮你理清 OkHttp 的内部脉络,我画了一张结构图。没有这张图,后续讲拦截器、连接池、Mock 测试时你会有点晕。

这张图展示了 OkHttp 的核心组件和请求从发起到响应返回的流程。注意看拦截器链条,这是 OkHttp 最灵活的地方,也是我们后续做 Mock 测试的关键切入点。

OkHttp 核心组件与请求流程 OkHttp 核心组件与请求流程 应用代码 (构建 Request / 发起 Call) Interceptor Chain (拦截器链) 1. RetryAndFollowUp 2. Bridge (桥接) 3. Cache (缓存) 4. Connect (连接) 网络 I/O(Socket / HTTP/2) Response 返回 拦截器是 Mock 测试的切入点

从这张图你能看到,OkHttp 把整个请求过程拆成了两层:应用层和网络层。中间那层拦截器链,就是它的灵魂。每个拦截器只做一件事,处理完了交给下一个。这种设计让扩展变得特别容易,我们后续课程要讲的 Mock 测试,就是通过自定义拦截器实现的。

几个重要的细节

  • OkHttpClient 建议复用。 每次创建新的 Client 会浪费连接池和线程池资源。我之前在循环里 new 过,结果连接池完全没有起作用。
  • Response body 需要关闭吗? OkHttp 会自动管理,但如果你用了 string() 或 bytes(),记得在 finally 块里 close() 或者用 try-with-resources。其实 string() 内部会帮你关闭,但为了代码健壮性,我建议显式关闭。
  • 超时设置很有必要。 默认超时是 10 秒,有些场景不够。我习惯给 connect 和 read 分别设 30 秒,write 设 60 秒。太短容易误报网络问题,太长又影响用户体验。
  • 别忘了添加 User-Agent。 有些服务器会检测 UA,没有的话可能会返回 403。我在一个爬虫项目里踩过这个坑,后来加了个模拟浏览器的 UA 就好了。
一句话总结第 1 章: OkHttp 是一个高性能的 HTTP 客户端,核心在于灵活且可扩展的拦截器机制。掌握基本的 GET/POST 请求写法,理解请求从发起到返回的完整流程,这是后续所有 Mock 测试和 CI 集成的基础。