CompletableFuture可用性和unit testing

我正在学习java 8 CompletableFuture并最终得到了这个。

所有的拳头,您如何看待这行代码? 我需要并行向不同的服务发送请求,然后等待所有服务响应并继续工作。

 //service A CompletableFuture serviceAFuture = CompletableFuture.supplyAsync( () -> this.ServiceA.retrieve(serviceARequest), serviceAExecutorService ); //service B CompletableFuture serviceBFuture = CompletableFuture.supplyAsync( () -> this.ServiceB.retrieve(serviceBRequest), serviceBExecutorService ); CompletableFuture.allOf(serviceAFuture, serviceBFuture).join(); ServiceAResponse responseA = serviceAFuture.join(); ServiceBResponse responseB = serviceBFuture.join(); 

甚至代码都在做我想要的,我在测试代码所在的类时遇到了问题。 我尝试使用Mockito并执行以下操作:

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

执行程序服务和服务响应在嘲笑,但测试永远不会结束,并且线程一直在等待这一行

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

我在这里缺少的任何暗示? 谢谢!

如果我是你,我会简单地模拟服务A和B以及你的执行者,然后通过注释@InjectMocks注入它们,因为它们是你的类的字段。

如果你想模拟你的Executor的方法execute ,你应该继续下一步简单地调用提供的Runnable的方法run

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

所以基本上你的测试会是这样的:

 @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()); } }