assertj: assertThat with CompletionStage is not waiting CompletableFuture to complete
Summary
I’m trying to do some test with firebase SDK things, the problem that the assertThat always failing with message:
[error] Expecting [error] <CompletableFuture[Incomplete]> [error] to be completed. [error] Be aware that the state of the future in this message might not reflect the one at the time when the assertion was per formed as it is evaluated later on, took 0.145 sec
and I’m not sure how to make it wait, I can do just a stupid solution with .join()
to make it work, but really it is not something that I’m looking for with this case.
Example
I have the following method of my service:
/**
* @param email
* @return token
*/
public CompletableFuture<String> getCustomToken(String email) {
CompletableFuture<String> future = new CompletableFuture<>();
ApiFuture<UserRecord> emailAsync = firebaseAuthProvider.get().getUserByEmailAsync(email);
emailAsync.addListener(() -> {
try {
UserRecord userRecord = emailAsync.get();
if (userRecord != null && userRecord.getUid() != null) {
ApiFuture<String> customTokenAsync = firebaseAuthProvider.get().createCustomTokenAsync(userRecord.getUid());
customTokenAsync.addListener(() -> {
try {
future.complete(customTokenAsync.get());
} catch (InterruptedException | ExecutionException e) {
future.completeExceptionally(e);
}
}, ec.current());
} else {
future.completeExceptionally(new BusinessException(MsgKeys.ERR_USER_UID_NOT_FOUND));
}
} catch (InterruptedException | ExecutionException exception) {
logger.error(exception.getMessage());
future.completeExceptionally(new BusinessException(MsgKeys.ERR_VALIDATE_TOKEN_FAILED, exception.getCause()));
}
}, ec.current());
return future;
}
Then This is the test method:
@Test
public void testLoginWithCustomTokenMustFailWithVerifyIdToken() {
logger.info("Testing login, we will create a custom token then verify it, it should be success until reach verifyIdToken and fail, because we can only verifyIdToken with " +
"tokens from frontend");
String email = config.getString("firebase.test.email");
CompletionStage<String> tokenFuture = firebaseAuthService.getCustomToken(email);
logger.info("Testing creating custom token for email " + email);
assertThat(tokenFuture).isCompletedWithValueMatching(token -> {
JsonNode jsonNode = Json.newObject().put("token", token);
logger.info("Trying to verify token " + token);
exception.expectCause(allOf(Matchers.instanceOf(FirebaseAuthException.class), hasProperty("message", startsWith("verifyIdToken() expects an ID token, but was given a custom token"))));
Http.RequestBuilder request = Helpers.fakeRequest()
.method(POST)
.bodyJson(jsonNode)
.uri("/api/user/firebaseLogin");
Result route = route(app, request);
return route.status() == 200;
}, "Creating custom token for " + email);
}
But when I replace CompletionStage<String> tokenFuture = firebaseAuthService.getCustomToken(email);
with CompletionStage<String> tokenFuture = CompletableFuture.completedFuture(firebaseAuthService.getCustomToken(email).join());
it will work.
Is it my code issue, or test not waiting correctly, or am I missing something?
Evironment:
Java 8 & 10:
java version “1.8.0_162” Java™ SE Runtime Environment (build 1.8.0_162-b12) Java HotSpot™ 64-Bit Server VM (build 25.162-b12, mixed mode)
java 10 2018-03-20 Java™ SE Runtime Environment 18.3 (build 10+46) Java HotSpot™ 64-Bit Server VM 18.3 (build 10+46, mixed mode)
Play Framework (2.6.x): https://www.playframework.com/documentation/2.6.x/JavaFunctionalTest
SBT: 0.13.15
AssertJ 3.9.1: libraryDependencies += "org.assertj" % "assertj-core" % "3.9.1" % Test
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 1
- Comments: 16 (11 by maintainers)
Commits related to this issue
- Add ability to wait on futures directly AssertJ upgrades will make our own CompletionStageAssert no longer work, without a direct replacement. Hence, we will need to change the API. See https://gith... — committed to Tradeshift/ts-reaktive by jypma 5 years ago
- Add ability to wait on futures directly AssertJ upgrades will make our own CompletionStageAssert no longer work, without a direct replacement. Hence, we will need to change the API. See https://gith... — committed to Tradeshift/ts-reaktive by jypma 5 years ago
forgotten mostly, now that we have added
succeedsWithin
for 3.17.0 https://github.com/joel-costigliola/assertj-core/pull/1930, we should addfailsWithin
tooThe
succeedsWithin
/failsWithin
pair seems a good option to me