使用Mockito测试CompletableFuture.supplyAsync时测试阻塞问题解决
解决Mockito测试CompletableFuture时无限阻塞的问题
你的测试之所以无限阻塞,核心原因是你创建的模拟CompletableFuture从未完成。在测试代码里,你实例化了userFuture和userEntityFuture,但没有调用complete()方法给它们设置返回值。当被测试的validateUserCounterparty方法执行到result.get()时,会一直等待Future的结果,导致测试永远无法结束。
解决方案
1. 让模拟的CompletableFuture处于已完成状态
不要手动创建空的CompletableFuture,而是直接用CompletableFuture.completedFuture()创建自带返回值的已完成Future,或者在创建空Future后主动调用complete()方法填充结果。
2. 完善测试依赖的模拟数据
需要模拟User、UserEntity对象,同时确保validate方法的返回值能正确传递(如果validate是UserValidationService的内部方法,要保证它返回的CompletableFuture也是已完成状态)。
修正后的测试代码示例
@ExtendWith(MockitoExtension.class) class UserValidationServiceTest { @Mock UserService userService; @Mock UserEntityService userEntityService; @InjectMocks UserValidationService userValidationService; // 注意:@ExtendWith(MockitoExtension.class)已自动初始化Mock,无需重复调用openMocks // @Before // public void init() { // MockitoAnnotations.openMocks(this); // } @Test public void validateUser() throws ExecutionException, InterruptedException { // 1. 构造测试用的模拟实体 User mockUser = new User(); mockUser.setUserId(1L); List<UserEntity> mockUserEntities = List.of( new UserEntity("US"), new UserEntity("ASIA"), new UserEntity("EUROPE") ); // 2. 创建已完成的CompletableFuture,直接返回模拟数据 CompletableFuture<User> userFuture = CompletableFuture.completedFuture(mockUser); CompletableFuture<List<UserEntity>> userEntityFuture = CompletableFuture.completedFuture(mockUserEntities); // 3. 配置Mock的方法返回行为 Mockito.when(userService.getUser(anyString())).thenReturn(userFuture); Mockito.when(userEntityService.getUserEntities(anyLong())).thenReturn(userEntityFuture); // 4. 构造测试请求 UserRequest request = UserRequest.builder() .userName("admin") .userEntities(List.of("US", "ASIA", "EUROPE")).build(); // 执行测试并验证结果 boolean result = userValidationService.validateUserCounterparty(request); assertTrue(result); } }
额外优化说明
- 移除冗余的
@Before初始化代码:@ExtendWith(MockitoExtension.class)会自动完成Mock对象的初始化,无需手动调用MockitoAnnotations.openMocks(this)。 - 关于
validate方法:如果它是UserValidationService的私有方法,需要确保模拟的userEntities和请求中的userEntities匹配,让方法逻辑返回true的CompletableFuture;如果需要更灵活的控制,可以将方法改为包私有,或者使用Mockito Spy来部分模拟UserValidationService的行为。
内容的提问来源于stack exchange,提问作者rakesh
相关产品推荐
相关产品推荐

