Метод mock void try catch catch и перехватить исключение при помощи EasyMock или Mockito - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть такой код, и я хочу полностью написать модульный тест для кода ниже. Я могу попробовать часть кода, но не могу понять, как я могу проверить часть исключения catch.

public class CacheUpdateTask implements Runnable {

    private WarehouseCache cache;

    private static final int EXPONENTIAL_MULTIPLIER = 100;

    private static final int MAXIMUM_TIME_LIMIT = 5;

    public CacheUpdateTask(
            final WarehouseCache cache) {
        this.cache = cache;
    }

    @Override
    public void run() {
        LOG.info("Requesting warehouse mapping from AService and updating the cache.");
        final Callable<Void> updateCache =
                new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                        cache.updateWarehouseCountryCodeCache();
                        return null;
                    }
                };
        final Retryer<Void> retryer = RetryerBuilder.<Void>newBuilder()
                .retryIfException()
                .withWaitStrategy(WaitStrategies.exponentialWait(EXPONENTIAL_MULTIPLIER, MAXIMUM_TIME_LIMIT,
                        TimeUnit.MINUTES))
                .withStopStrategy(StopStrategies.neverStop())
                .build();
        try {
            retryer.call(updateCache); // this is also a void method, so no return here
        } catch (ExecutionException | RetryException e) {
            e.printStackTrace();
            LOG.error(e);
            LOG.error("Exception when refreshing the cache.");
        }
        LOG.info("Cache has been updated.");
    }
}

Указывает на примечание

  • Здесь ретритер настроен на neverStop. Всякий раз, когда возникает исключение при вызове retryer.call(updateCache);, повторная попытка на самом деле повторяется. Таким образом, в блоке try, когда retryer.call(updateCache) выдает исключение, выполнение не переходит к блоку перехвата, а просто продолжает пытаться.
  • Я пытался имитировать код c в блоке try, чтобы вызвать какое-то исключение несколькими способами, но он никогда не вызывает код в catch. Ниже приведен код моей последней попытки перед созданием этого вопроса. В большинстве моих попыток тесты выполняются успешно, но я никогда не заканчиваю тестировать блок catch
  • Ниже код выполняется успешно, но на самом деле он не достигает catch block на основе теста покрытия кода.
@Test (expected = ExecutionException.class)
    public void test_UpdateCacheFOServiceRunException() throws Exception {
        WarehouseCacheFOServiceUpdateTask mockUpdateTaskFOService;
        WarehouseCache mockClientCache;
        mockUpdateTaskFOService = Mockito.mock(WarehouseCacheFOServiceUpdateTask.class);
        mockClientCache = Mockito.mock(WarehouseCache.class);


        Mockito.doThrow(ExecutionException.class)
                .when(mockClientCache).updateWarehouseCountryCodeCacheFOService();
        //clientCache.updateWarehouseCountryCodeCacheFOService();
        //Mockito.doThrow( ExecutionException.class )
          //      .when(mockUpdateTaskFOService).run();
        mockClientCache.updateWarehouseCountryCodeCacheFOService();
        mockUpdateTaskFOService.run();

    }

1 Ответ

0 голосов
/ 27 апреля 2020

Ваш тест неверен, чтобы ожидать это

@Test(expected = ExecutionException.class)

Если вы посмотрите на свой код, вы увидите, что вы поймали, зарегистрировали и проглотили это исключение. Он никогда не перебрасывается, поэтому ваш тест не должен этого ожидать.

Кроме этого, ваш тест выглядит в целом правильно. У вас нет средств для каких-либо значимых утверждений, поскольку регистратор имеет следующий статус: c.

. Это немного вводит в заблуждение

Mockito.doThrow(ExecutionException.class)

, поскольку ExecutionException вы пытаетесь поймать исключение, которое Retryer должно обернуть оригинальное исключение. То, что вы сейчас симулируете, это ExecutionException обёртка ExecutionException. Это будет работать ради вашего теста, но не реально c. Я бы добавил генерик c Exception.class (который затем будет обернут).


В вашем коде есть небольшая ошибка, которая может привести к вводящей в заблуждение регистрации. Эта строка будет выполняться, даже если исключение было сгенерировано, перехвачено и зарегистрировано.

LOG.info("Cache has been updated.");

У вас есть два варианта: вы можете поместить return в перехват или переместить строку регистрации.

try {
    retryer.call(updateCache);
    LOG.info("Cache has been updated."); // this
} catch (ExecutionException | RetryException e) {
    e.printStackTrace();
    LOG.error(e);
    LOG.error("Exception when refreshing the cache.");
    return; // or this
}
...