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

如何使用Spock框架Mock java.net.http.HttpClient?

解决方案:Mock java.net.http.HttpClient 的 send 调用(无需重构代码)

问题背景

现有静态方法提供HttpClient实例:

@CompileStatic
private static HttpClient getClient() {
    return HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(5))
            .build()
}

业务代码中通过该实例调用第三方API:

final HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString())

无法重构代码,尝试GroovySpy(global: true)、GroovyMock(global: true)(包括针对HttpClientImpl)均无效,且因依赖过多无法重写getClient()方法,需要Mock指定返回值。

可行方案:使用PowerMock + Mockito 静态Mock

由于目标是Mock静态方法HttpClient.newBuilder()的链式调用,从而控制返回的HttpClient实例,进而Mock其send方法,步骤如下:

  1. 引入依赖
    确保测试依赖中包含PowerMock和Mockito的适配包(以Gradle为例):
testImplementation "org.powermock:powermock-module-junit4:2.0.9"
testImplementation "org.powermock:powermock-api-mockito2:2.0.9"
testImplementation "org.mockito:mockito-core:3.12.4"
  1. 编写测试代码
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;

@RunWith(PowerMockRunner.class)
@PrepareForTest(HttpClient.class) // 标记需要Mock的静态类
public class YourServiceTest {

    @Mock
    private HttpClient mockHttpClient;
    @Mock
    private HttpClient.Builder mockBuilder;
    @Mock
    private HttpResponse<String> mockResponse;

    @Test
    public void testApiCall() throws Exception {
        // 1. Mock HttpClient.newBuilder() 返回我们的mockBuilder
        mockStatic(HttpClient.class);
        when(HttpClient.newBuilder()).thenReturn(mockBuilder);

        // 2. 链式Mock Builder的配置方法,最终返回mockHttpClient
        when(mockBuilder.version(any(HttpClient.Version.class))).thenReturn(mockBuilder);
        when(mockBuilder.connectTimeout(any())).thenReturn(mockBuilder);
        when(mockBuilder.build()).thenReturn(mockHttpClient);

        // 3. Mock send方法的返回值
        when(mockResponse.body()).thenReturn("Mocked API Response");
        when(mockHttpClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class)))
                .thenReturn(mockResponse);

        // 执行你的业务方法,此时会使用我们Mock的HttpClient
        YourService.yourBusinessMethod();

        // 验证逻辑(可选)
        // verify(mockHttpClient).send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class));
    }
}

关键说明

  • PowerMock允许Mock静态方法、私有方法等Mockito无法覆盖的场景,正好适配HttpClient.newBuilder()这种静态创建实例的场景。
  • 通过链式Mock Builder的每一步调用,确保最终返回我们创建的Mock HttpClient实例,这样后续的send调用就能被我们控制。
  • 无需修改原有业务代码,完全通过测试框架实现Mock。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:47:06