Java 8 测试并发

Java 8 Testing Concurrency

所以...

我有这个实用程序 class 在初始调用在给定时间后未返回后执行重试(理论上是任何事情),并不断这样做直到任何源 returns 数据或者直到所有人都筋疲力尽。这使用 ExecutorCompletionService.poll 方法来触发何时重试。请参阅以下实用程序代码 class...

final RetrySources[] retrySources = getRetrySources(originalSource);

Future<T> resultFuture = null;
final List<Future<T>> futures = new ArrayList<>(retrySources.length);
for (int tryIndex = 0; tryIndex < retrySources.length && resultFuture == null; tryIndex++) {
    final int tryIndexCopy = tryIndex;
    futures.add(ecs.submit(() -> client.call(retrySources[tryIndexCopy], tryIndexCopy)));
    resultFuture = ecs.poll(millisBeforeRetry, TimeUnit.MILLISECONDS);
}

if (resultFuture == null) {
    resultFuture = ecs.take();
}

return resultFuture.get();

...我的问题是我正在重写测试以不使用睡眠,而是使用 CountDownLatch。请参阅下面我的一项测试...

    @Test
    public void call_firstRetryFinishesAfterLimitButBeforeSecondRetryDoes_triggersSecondRetryButUsesFirstResult() throws Exception {
        final String readResult1 = "a";
        final String readResult2 = "b";

        final CountDownLatch signal1 = new CountDownLatch(1);
        final CountDownLatch signal2 = new CountDownLatch(1);

        expect(mockReadOperation.call(readOptions[0], 0)).andStubAnswer(() -> {
            signal1.await(); // This causes the test to spin forever
            // Thread.sleep(1000); // Swapping the line above for this, makes it work
            return readResult1;
        });

        expect(mockReadOperation.call(readOptions[1], 1)).andStubAnswer(() -> {
            signal1.countDown();
            signal2.await(); // For this test case, make the second retry never return
            return readResult2;
        });

        replay(mockReadOperation);

        final ReadOption readOption = ReadOption.primary();
        final String result = subject.call(readOption);

        assertThat(result).isEqualTo("a");
    }

...请注意我的 ExecutorCompletionService 已定义...

private final ExecutorCompletionService executorCompletionService = new ExecutorCompletionService(Executors.newFixedThreadPool(2));

...因为我的测试是 运行 在主线程中,并且每次调用都是 运行 它是自己的线程作为 ExecutorCompletionService 池的一部分,我不理解为什么 signal1.await(); 会导致测试永远旋转并注意评论,即切换那条单线以进入睡眠状态会导致测试通过。

非常感谢任何帮助。

这可能是由于 replay(mockReadOperation); 您在何处激活(执行)模拟。 ??

注意:我从未使用过 easy-mock,但快速 google 表明 replay 激活了模拟,这似乎符合答案,我可能错了。

如果我是对的,而你总是需要在 easymock 中进行 replay 模拟,那么也许解决方案是,切换到 Mockito :p!