Java 8 Тестирование параллелизма - PullRequest
0 голосов
/ 09 июня 2018

SO ...

У меня есть этот служебный класс, который выполняет повторные попытки (к чему-либо, теоретически) после того, как первоначальный вызов не вернулся через заданный промежуток времени, и постоянно делает это, пока какой-либо источник не вернет данныеили пока все не исчерпаны.При этом используется метод ExecutorCompletionService .poll для запуска, когда нужно повторить попытку.См. Следующий код для служебного класса ...

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

... моя проблема в том, что я переписываю тесты, чтобы не использовать sleep, а вместо этого использовать 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(); заставляет тест вращаться вечно и отмечает комментарий, что переключение этой единственной строкидля сна, заставляет пройти тест.

Любая помощь очень ценится.

1 Ответ

0 голосов
/ 09 июня 2018

Это, вероятно, из-за replay(mockReadOperation);, где вы активируете (выполняете) макеты.??

Примечание: я никогда не использовал easy-mock, но быстрый Google показывает, что replay активирует макеты, и это, кажется, соответствует ответу, я могу ошибаться.

ЕслиЯ прав, и вы всегда должны replay издеваться в easymock, тогда, возможно, решение состоит в том, чтобы переключиться на Mockito: p!

...