You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为使用OkHttp调用第三方API的Java方法编写单元测试?

正确实现单元测试的步骤

1. 依赖准备

首先确保测试依赖引入完整,和你项目中OkHttp版本保持一致:

<!-- MockWebServer依赖 -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>mockwebserver</artifactId>
    <version>你的OkHttp版本号</version>
    <scope>test</scope>
</dependency>
<!-- 静态方法Mock依赖(可选,用来跳过QueryUtils、PartitionUtil的逻辑校验) -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>4.8.1</version>
    <scope>test</scope>
</dependency>

2. 完整测试实现

以下是基于JUnit5的标准测试代码:

import okhttp3.OkHttpClient;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import static org.mockito.Mockito.mockStatic;
import static org.junit.jupiter.api.Assertions.*;

// 假设你的业务方法放在AuditDataService类中
class AuditDataServiceTest {
    private MockWebServer mockServer;
    private OkHttpClient okHttpClient;
    private final AuditDataService auditDataService = new AuditDataService();

    @BeforeEach
    void init() throws Exception {
        // 启动Mock服务
        mockServer = new MockWebServer();
        mockServer.start();
        okHttpClient = new OkHttpClient();
    }

    @AfterEach
    void close() throws Exception {
        // 关闭Mock服务释放端口
        mockServer.shutdown();
    }

    @Test
    void getAuditData_returnCorrectDataWhenRequestSuccess() throws IOException, InterruptedException {
        // 1. 构造符合GraphQL规范的响应体,必须包含data层级匹配你业务代码的提取规则
        String mockResponseBody = """
            {
                "data": {
                    "auditData": [
                        {"id": 1001, "remark": "测试审计数据1", "operator": "admin"},
                        {"id": 1002, "remark": "测试审计数据2", "operator": "user"}
                    ]
                }
            }
            """;

        // 2. 入队Mock响应
        MockResponse mockResponse = new MockResponse()
                .setResponseCode(200)
                .addHeader("Content-Type", "application/json; charset=utf-8")
                .setBody(mockResponseBody);
        mockServer.enqueue(mockResponse);

        // 3. Mock静态工具类(如果不需要校验工具类逻辑可以这么写,要测试工具类则去掉该部分传真实参数即可)
        try (MockedStatic<QueryUtils> queryUtilsMock = mockStatic(QueryUtils.class);
             MockedStatic<PartitionUtil> partitionUtilMock = mockStatic(PartitionUtil.class)) {
            // 定义静态方法返回值
            String mockGraphqlQuery = "query { auditData(id:1) { id remark } }";
            queryUtilsMock.when(() -> QueryUtils.getAuditDataQuery(1, 86, 202401, 1, "read_partition_01"))
                    .thenReturn(mockGraphqlQuery);
            partitionUtilMock.when(() -> PartitionUtil.getReadPartition("test_token_abc"))
                    .thenReturn("read_partition_01");

            // 4. 拿到Mock服务的地址,传入业务方法(这是大多数人测试失败的核心原因:之前传了真实第三方地址,请求没打到Mock服务上)
            String mockServerUrl = mockServer.url("/graphql").toString();

            // 5. 调用待测试方法
            List<AuditData> result = auditDataService.getAuditData(
                    okHttpClient, 1, 86, 202401, 1, mockServerUrl, "test_token_abc"
            );

            // 6. 校验返回结果
            assertEquals(2, result.size());
            assertEquals("admin", result.get(0).getOperator());

            // 7. 可选:校验请求参数是否符合预期
            RecordedRequest actualRequest = mockServer.takeRequest();
            assertEquals("POST", actualRequest.getMethod());
            assertEquals("Bearer test_token_abc", actualRequest.getHeader("Authorization"));
            assertTrue(actualRequest.getBody().readUtf8().contains(mockGraphqlQuery));
        }
    }
}

3. 常见失败原因排查

  • 没有将MockWebServer生成的动态地址传入业务方法,而是硬编码了真实第三方API地址
  • 响应体格式不符合GraphQL规范,缺少data层级导致extractValueAsObject提取结果为空
  • AuditData类没有无参构造、Getter/Setter方法,导致反序列化失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 14:42:02