[英]Testing CompletableFuture.supplyAsync with Mockito
I am trying to test CompletableFuture.supplyAsync function with mockito but the test is not completing probably because the completable future is not returning.我正在尝试使用 mockito 测试 CompletableFuture.supplyAsync function 但测试未完成可能是因为可完成的未来没有返回。 I am not sure what I am missing in the code.我不确定我在代码中缺少什么。 Can anyone please help.任何人都可以请帮忙。
I have written the code as follows.我编写了如下代码。 So there are UserService class which returns User, UserEntityService class which returns users entities and a validation class to check if the entities belongs to the user or not.因此,有返回用户的 UserService class,返回用户实体的 UserEntityService class 和验证 class 以检查实体是否属于用户。
I want to test if the passed entities belongs to user or not.我想测试通过的实体是否属于用户。
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;
}
}
And the test case is written as并且测试用例写成
@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);
}
}
On executing this test, it goes into infinite loop and never stops.在执行这个测试时,它会进入无限循环并且永远不会停止。 I guess its because the completable future is not returning but I dont have enough knowledge on how to prevent it.我想这是因为可完成的未来没有回来,但我对如何防止它没有足够的知识。
What modification should I do to prevent it?我应该做哪些修改来防止它?
In your test method you're creating CompletableFuture
instances using new
.在您的测试方法中,您正在使用new
创建CompletableFuture
实例。 JavaDoc states : JavaDoc 状态:
public CompletableFuture()公共 CompletableFuture()
Creates a new incomplete CompletableFuture.创建一个新的不完整的 CompletableFuture。
So the objects you're creating are never completing, that's why the test is running infinitely.因此,您正在创建的对象永远不会完成,这就是测试无限运行的原因。 It's not actually a loop, but waiting on a blocking operation to be finished, which never happens.它实际上不是一个循环,而是等待阻塞操作完成,这永远不会发生。
What you need to do is define a CompletableFuture
that completes - immediately or after some time.您需要做的是定义一个CompletableFuture
完成 - 立即或一段时间后。 The simplest way of doing that is by using the static completedFuture() method :最简单的方法是使用static completedFuture() 方法:
CompletableFuture<User> userFuture =
CompletableFuture.completedFuture(new User());
CompletableFuture<List<UserEntity>> userEntityFuture =
CompletableFuture.completedFuture(List.of(new UserEntity()));
Thanks to that given objects are returned and the code can be executed fully.由于返回了给定的对象,并且代码可以完全执行。 You can test errors in a similar way by using the failedFuture() method .您可以使用failedFuture() 方法以类似的方式测试错误。
I've created a GitHub repo with a minimal reproducible example - the test presented there passes.我创建了一个 GitHub 存储库,其中包含一个最小的可重现示例- 那里的测试通过了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.