I have a service SomeService with one method to do some logic.
@Override
public CompletableFuture<Boolean> process(User user) {
Objects.requiredNonNull(user, "user must not be null");
// other logic...
}
Then I have a test for this.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SomeService.class })
public class SomeServiceTest {
@Autowired private SomeService tested;
@Test
public void user_null_expect_NullPointerException() {
assertThatThrownBy(() -> tested.process(null))
.isInstanceOf(NullPointerException.class)
.hasMessage("user must not be null");
}
}
It worked fine until I decided to make that method asynchronous.
@Async
@Override
public CompletableFuture<Boolean> process(User user) {
Objects.requiredNonNull(user, "user must not be null");
// other logic...
}
So, now it doesn't work because of Spring proxies. Does anyone have an idea how I must configure my test to make it work again?
Ok, I have a solution. The problem is not in async method, the problem is in wrong assertions. I didn't know AssertJ is able to test CompletableFuture.
So my solution is this:
@Test
public void user_null_expect_NullPointerException() {
final CompletableFuture<Boolean> result = getCompletedResult(null);
assertThat(result)
.isCompletedExceptionally()
.hasFailedWithThrowableThat()
.isInstanceOf(NullPointerException.class)
.hasMessage("user must not be null");
}
private CompletableFuture<Boolean> getCompletedResult(User user) {
final CompletableFuture<Boolean> result = tested.process(user);
await().atMost(10, TimeUnit.SECONDS).until(result::isDone);
return result;
}
If you have a better solution, let me know.