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

调用Mockito模拟对象时遭遇HTTP连接超时问题

解决RequestClient(final类) Mock失效导致HTTP超时问题

你的测试抛出连接超时异常的核心原因是:你在测试中创建的RequestClient Mock实例,根本没有被CorrectionService使用。CorrectionService内部通过new RequestClient<>(new HttpClientFactory())直接创建新对象,和你测试里mock的对象完全是两个独立实例,导致mock的send()方法从未生效,代码还是发起了真实的HTTP请求,最终超时。

方案一:重构代码使用构造注入(推荐)

这是最符合依赖注入原则的方案,将RequestClient从CorrectionService内部创建改为外部注入,测试时可直接传入Mock对象。

修改CorrectionService:

public class CorrectionService {
    private final AccessTokenCacheService accessTokenCacheService;
    private final RequestClient<BookingDetails> bookingRequestClient;

    // 构造方法注入依赖
    public CorrectionService(AccessTokenCacheService accessTokenCacheService, 
                             RequestClient<BookingDetails> bookingRequestClient) {
        this.accessTokenCacheService = accessTokenCacheService;
        this.bookingRequestClient = bookingRequestClient;
    }

    public BookingDetails getBooking(String id, String city) throws URISyntaxException {
        // 省略业务逻辑...
        // 使用注入的RequestClient,不再自行new
        ApiResponse<BookingDetails> apiResponse = bookingRequestClient.send(request, BookingDetails.class);
        return apiResponse.getData();
    }
}

修改测试代码:

@Mock
AccessTokenCacheService accessTokenCacheService;

// 直接Mock泛型类型的RequestClient,inline mock支持final类
@Mock
RequestClient<BookingDetails> bookingRequestClient;

@InjectMocks
CorrectionService correctionService;

@Test
void test() throws URISyntaxException {
    when(accessTokenCacheService.getCacheAccessToken(anyString())).thenReturn("token-abc");
    
    ApiResponse<BookingDetails> mockApiResponse = mock(ApiResponse.class, withSettings().mockMaker(MockMakers.INLINE));
    when(bookingRequestClient.send(any(), eq(BookingDetails.class))).thenReturn(mockApiResponse);
    when(mockApiResponse.getData()).thenReturn(new BookingDetails());
    
    assertAll(() -> correctionService.getBooking("id1", "New York"));
}

方案二:无法重构时,用PowerMock拦截对象创建(不推荐)

如果受项目限制无法修改CorrectionService代码,可以用PowerMock拦截new RequestClient的操作,让它返回预先mock的对象。

测试代码示例:

@RunWith(PowerMockRunner.class)
// 指定需要拦截的类
@PrepareForTest({CorrectionService.class, RequestClient.class})
public class CorrectionServiceTest {
    @Mock
    AccessTokenCacheService accessTokenCacheService;

    @Mock
    RequestClient<BookingDetails> bookingRequestClient;

    @InjectMocks
    CorrectionService correctionService;

    @Test
    void test() throws Exception {
        when(accessTokenCacheService.getCacheAccessToken(anyString())).thenReturn("token-abc");
        
        ApiResponse<BookingDetails> mockApiResponse = mock(ApiResponse.class);
        when(bookingRequestClient.send(any(), eq(BookingDetails.class))).thenReturn(mockApiResponse);
        when(mockApiResponse.getData()).thenReturn(new BookingDetails());
        
        // 拦截CorrectionService内部new RequestClient的操作,返回mock实例
        PowerMockito.whenNew(RequestClient.class).withAnyArguments().thenReturn(bookingRequestClient);
        
        assertAll(() -> correctionService.getBooking("id1", "New York"));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 05:43:25