Mocked ExecutorService始终返回相同的模拟Future

时间:2016-03-01 01:09:52

标签: junit future executorservice powermock easymock

我实现了一个模拟ExecutorService,可以立即返回结果而无需创建线程:

public static ExecutorService createMock() throws Exception {
    ExecutorService executorServiceMock = EasyMock.createMock(ExecutorService.class);
    Future future = EasyMock.createMock(Future.class);
    Capture<Callable<?>> callableCapture = new Capture<>();
            EasyMock.expect(executorServiceMock.submit(EasyMock.<Callable<?>>capture(callableCapture))).andReturn(future).anyTimes();
    EasyMock.expect(future.get()).andAnswer(() -> callableCapture.getValue().call()).anyTimes();

    executorServiceMock.shutdown();
    EasyMock.expectLastCall().anyTimes();
    EasyMock.replay(future, executorServiceMock);
    return executorServiceMock;
}

问题是它总是返回相同的[模拟] Future对象。我需要根据传递给executorServiceMock.submit()的可调用对象返回Future mock的新实例 我试图使用PowerMock.expectNew(Future.class),但它抱怨“在类'java.util.concurrent.Future'中找不到带有参数类型的构造函数:[]”

3 个答案:

答案 0 :(得分:0)

首先"Don't mock type you don't own!"。通过链接,您可能会发现为什么不应该这样做的几个原因。

但是,如果你真的想这样做,那么通过回答替换return mock会每次创建一个新的nock:

EasyMock.expect(executorServiceMock.submit(EasyMock.<Callable<?>>capture(callableCapture))).andAnswer(() -> {
    Future future = EasyMock.createMock(Future.class);
    EasyMock.expect(future.get()).andAnswer(() -> callableCapture.getValue().call()).anyTimes();
    EasyMock.replay(future);
    return future;
}).anyTimes();

顺便说一下,您不能指望PowerMock.expectNew(Future.class)因为Future是界面而无法创建。

答案 1 :(得分:0)

捕获将始终返回最后捕获的对象。在您的情况下,您似乎想要同步提交和获取。

所以,我认为你应该做到以下几点:

    ExecutorService executorServiceMock = createMock(ExecutorService.class);

    expect(executorServiceMock.submit(EasyMock.<Callable<?>>anyObject()))
        .andAnswer(() -> {
            Future future = createMock(Future.class);
            Object value = ((Callable<?>) getCurrentArguments()[0]).call();
            expect(future.get()).andReturn(value);
            replay(future);
            return future;
        })
        .anyTimes();

    executorServiceMock.shutdown();
    expectLastCall().anyTimes();

    replay(executorServiceMock);

    return executorServiceMock;

答案 2 :(得分:0)

下面的代码解决了我的问题。

@Mock
private ThreadPoolExecutor executorPool;

Future<String> result = CompletableFuture.completedFuture("S3PATH");
when(executorPool.submit(Mockito.<Callable<String>> anyObject())).thenReturn(result);