gpt4 book ai didi

java - 使用 Mockito 测试 CompletableFuture.supplyAsync

转载 作者:行者123 更新时间:2023-12-03 08:03:03 31 4
gpt4 key购买 nike

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

我写的代码如下。因此有返回 User 的 UserService 类、返回用户实体的 UserEntityService 类和一个检查实体是否属于用户的验证类。

我想测试传递的实体是否属于用户。

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);

}
}

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

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

最佳答案

在您的测试方法中,您将使用 new 创建 CompletableFuture 实例。 JavaDoc states :

public CompletableFuture()

Creates a new incomplete CompletableFuture.

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

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

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

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


我创建了a GitHub repo with a minimal reproducible example - 那里提出的测试通过了。

关于java - 使用 Mockito 测试 CompletableFuture.supplyAsync,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73332148/

31 4 0