微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – CompletableFuture可用性和单元测试

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

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

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

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

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

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

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

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

解决方法

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

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

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

原文地址:https://www.jb51.cc/java/239808.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐