在Java中模拟ExecutorService invokeAll方法

时间:2018-07-06 20:45:59

标签: java mockito executorservice invokeall

我正在尝试模拟ExecutorService,但它一直在给出编译错误。我正在尝试的代码如下:

ExecutorService executorService = mock(ExecutorService.class);
Future<A> mockedFuture = mock(Future.class);
List<Future<A>> list = Lists.newArrayList(mockedFuture);

when(executorService.invokeAll(any())).thenReturn(list);

当我编译它时,它返回以下错误:

error: no suitable method found for thenReturn(List<Future<A>>)
[javac]         when(executorService.invokeAll(any())).thenReturn(futureList);
[javac]                                               ^
[javac]     method OngoingStubbing.thenReturn(List<Future<Object>>) is not applicable
[javac]       (argument mismatch; List<Future<A>> cannot be converted to List<Future<Object>>)
[javac]     method OngoingStubbing.thenReturn(List<Future<Object>>,List<Future<Object>>...) is not applicable
[javac]       (argument mismatch; List<Future<A>> cannot be converted to List<Future<Object>>)

有什么主意吗?

2 个答案:

答案 0 :(得分:2)

此处Mockito.any()返回由调用目标推断的类型,即executorService.invokeAll()。但是executorService.invokeAll()也没有声明更具体的类型,因为它也依赖于目标推断:Mockito.when(...)

any()返回的类型取决于invokeAll()返回的类型,而when()返回的类型也取决于。

但是invokeAll()when()都没有在通用集合中指定A类型。

因此T方法的通用invokeAll()类型定义为:

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)

将被编译器视为Object,例如:

<Object> List<Future<Object>> invokeAll(Collection<? extends Callable<Object>> tasks)

因此any()将返回Collection<? extends Callable<Object>>类型。

在这些情况下,无法返回thenReturn()但声明的List<Future<Object>>类型的List<Future<A>>无法编译:

argument mismatch; List<Future<A>> cannot be converted to List<Future<Object>>)

要解决您的问题,您需要对Mockito.any()进行未经检查的强制转换(但您知道它会起作用):

Mockito.when(executorService.invokeAll((Collection<Callable<A>>)Mockito.any())).thenReturn(list);

或者,通过在变量中显式设置Mockito.any()的返回值来解决目标推断:

Collection<Callable<A>> any = Mockito.any();
Mockito.when(executorService.invokeAll(any)).thenReturn(list);

答案 1 :(得分:1)

您应该在以下方面获得更大的成功

    ExecutorService executorService = mock(ExecutorService.class);
    Future<Object> mockedFuture = mock(Future.class);
    List<Future<Object>> list = Lists.newArrayList(mockedFuture);

    when(executorService.invokeAll(any())).thenReturn(list);

错误消息有一个提示:

argument mismatch; List<Future<A>> cannot be converted to List<Future<Object>>

这是因为对于Java泛型,List<Future<A>不是List<Future<Object>>Future<A>也不是Future<Object>)。

为什么会出现这种情况,有很多很好的解释,请看一下Java的SO的SO。