Java – completable future usability and unit testing

I was learning java 8 completable future and finally got this

All fists, what do you think of this line of code? I need to send requests to different services in parallel, then wait for all services to respond and continue working

//service A
CompletableFuture<ServiceAResponse> serviceAFuture = CompletableFuture.supplyAsync(
    () -> this.ServiceA.retrieve(serviceARequest),serviceAExecutorService
);

//service B
CompletableFuture<ServiceBResponse> serviceBFuture = CompletableFuture.supplyAsync(
    () -> this.ServiceB.retrieve(serviceBRequest),serviceBExecutorService
);

CompletableFuture.allOf(serviceAFuture,serviceBFuture).join();
ServiceAResponse responseA = serviceAFuture.join();
ServiceBResponse responseB = serviceBFuture.join();

Even the code is doing what I want. I have a problem testing the class where the code is located I try to use mockito and do the following:

doAnswer(invocation -> CompletableFuture.completedFuture(this.serviceAResponse))
    .when(this.serviceAExecutorService)
    .execute(any());

The executor service and service response are mocking, but the test will never end, and the thread has been waiting for this line

CompletableFuture.allOf(serviceAFuture,serviceBFuture).join();

Any hint I'm missing here? thank you!

Solution

If I were you, I would simply simulate services a and B and your executors, and then inject them through the annotation @ injectmocks, because they are the domain of your class

If you want to simulate the method execution of your executor, you should continue to the next step and simply call the provided runnable method to run:

doAnswer(
    (InvocationOnMock invocation) -> {
        ((Runnable) invocation.getArguments()[0]).run();
        return null;
    }
).when(serviceAExecutorService).execute(any(Runnable.class));

So basically your test will be like this:

@RunWith(MockitoJUnitRunner.class)
public class CompletableFutureServiceTest {

    // The mock of my service A
    @Mock
    private ServiceA ServiceA;
    // The mock of my service B
    @Mock
    private ServiceB ServiceB;
    // The mock of your executor for the service A
    @Mock
    private Executor serviceAExecutorService;
    // The mock of your executor for the service B
    @Mock
    private Executor serviceBExecutorService;
    // My class in which I want to inject the mocks
    @InjectMocks
    private CompletableFutureService service;

    @Test
    public void testSomeMethod() {
        // Mock the method execute to call the run method of the provided Runnable
        doAnswer(
            (InvocationOnMock invocation) -> {
                ((Runnable) invocation.getArguments()[0]).run();
                return null;
            }
        ).when(serviceAExecutorService).execute(any(Runnable.class));
        doAnswer(
            (InvocationOnMock invocation) -> {
                ((Runnable) invocation.getArguments()[0]).run();
                return null;
            }
        ).when(serviceBExecutorService).execute(any(Runnable.class));

        ServiceAResponse serviceAResponse = ... // The answer to return by service A
        // Make the mock of my service A return my answer
        when(ServiceA.retrieve(any(ServiceARequest.class))).thenReturn(
            serviceAResponse
        );
        ServiceBResponse serviceBResponse = ... // The answer to return by service B
        // Make the mock of my service B return my answer
        when(ServiceB.retrieve(any(ServiceBRequest.class))).thenReturn(
            serviceBResponse
        );

        // Execute my method
        ServiceResponse response = service.someMethod(
            new ServiceARequest(),new ServiceBRequest()
        );

        // Test the result assuming that both responses are wrapped into a POJO
        Assert.assertEquals(serviceAResponse,response.getServiceAResponse());
        Assert.assertEquals(serviceBResponse,response.getServiceBResponse());
    }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>