调用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
相关产品推荐
相关产品推荐

