繁体   English   中英

使用 Mockito 测试 CompletableFuture.supplyAsync

[英]Testing CompletableFuture.supplyAsync with Mockito

我正在尝试使用 mockito 测试 CompletableFuture.supplyAsync function 但测试未完成可能是因为可完成的未来没有返回。 我不确定我在代码中缺少什么。 任何人都可以请帮忙。

我编写了如下代码。 因此,有返回用户的 UserService class,返回用户实体的 UserEntityService class 和验证 class 以检查实体是否属于用户。

我想测试通过的实体是否属于用户。

class UserService {

    CompletableFuture<User> getUser(String userName) {
        log.info("Fetching User with username {}", userName);
        return CompletableFuture.supplyAsync(
                () -> getUserByPortalUserName(userName));
    }
}
class UserEntityService {

    CompletableFuture<List<UserEntity>> getUserEntities(Long userId) {
        log.info("Retrieving all entities for user id {}", userId);
        return CompletableFuture.supplyAsync(
                () -> getAllByUserId(userId));
    }
}
class UserValidationService {

    public boolean validateUserCounterparty(UserRequest request) 
                   throws ExecutionException, InterruptedException {
        CompletableFuture<Boolean> result = userService.getUser(request.getUserName())
                .thenCompose(user -> userEntityService.getUserEntities(user.getUserId()))
                .thenCompose(userEntities -> validate(userEntities, request.getUserEntities()));

        Boolean validationStatus = result.get();
        if (!validationStatus) {
            log.error("Validation failed for user name {}", request.getUserName());
        }
        return validationStatus;
    }
}

并且测试用例写成

@ExtendWith(MockitoExtension.class)
class UserValidationServiceTest {

    @Mock
    UserService userService;

    @Mock
    UserEntityService userEntityService;

    @InjectMocks
    UserValidationService userValidationService;

    @Before
    public void init() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void validateUser() throws ExecutionException, InterruptedException {
        CompletableFuture<User> userFuture = new CompletableFuture<>();
        CompletableFuture<List<UserEntity>> userEntityFuture = new CompletableFuture<>();

        Mockito.doReturn(userFuture).when(userService).getUser(anyString());
        Mockito.doReturn(userEntityFuture).when(userEntityService).getUserEntities(anyLong());

        UserRequest request = UserRequest.builder()
                .userName("admin")
                .userEntities(List.of("US", "ASIA", "EUROPE")).build();


        boolean result = validationService.validateUserCounterparty(request);
        assertTrue(result);

    }
}

在执行这个测试时,它会进入无限循环并且永远不会停止。 我想这是因为可完成的未来没有回来,但我对如何防止它没有足够的知识。

我应该做哪些修改来防止它?

在您的测试方法中,您正在使用new创建CompletableFuture实例。 JavaDoc 状态

公共 CompletableFuture()

创建一个新的不完整的 CompletableFuture。

因此,您正在创建的对象永远不会完成,这就是测试无限运行的原因。 它实际上不是一个循环,而是等待阻塞操作完成,这永远不会发生。

您需要做的是定义一个CompletableFuture完成 - 立即或一段时间后。 最简单的方法是使用static completedFuture() 方法

CompletableFuture<User> userFuture =
        CompletableFuture.completedFuture(new User());
CompletableFuture<List<UserEntity>> userEntityFuture =
        CompletableFuture.completedFuture(List.of(new UserEntity()));

由于返回了给定的对象,并且代码可以完全执行。 您可以使用failedFuture() 方法以类似的方式测试错误。


我创建了一个 GitHub 存储库,其中包含一个最小的可重现示例- 那里的测试通过了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM