«1. Обзор

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

Но иногда нам может понадобиться имитировать методы зависимостей, которые ничего не возвращают.

В этом уроке мы увидим, когда и как имитировать методы void с помощью EasyMock.

2. Зависимость от Maven

Во-первых, давайте добавим зависимость EasyMock к нашему pom.xml:

<dependency>
    <groupId>org.easymock</groupId>
    <artifactId>easymock</artifactId>
    <version>4.0.2</version>
    <scope>test</scope>
</dependency>

3. Когда следует имитировать метод void

Когда мы тестируем классы с зависимостями, мы обычно хотите охватить все значения, возвращаемые зависимостью. Но иногда методы зависимости не возвращают значение. Итак, если ничего не возвращается, зачем нам издеваться над методом void?

Несмотря на то, что методы void не возвращают значения, они могут иметь побочные эффекты. Примером этого является метод Session.save(). Когда мы сохраняем новый объект, метод save() генерирует идентификатор и устанавливает его для переданного объекта.

По этой причине мы должны имитировать метод void для имитации различных результатов обработки.

Другой случай, когда насмешка может пригодиться, — это тестирование исключений, выдаваемых методом void.

4. Как смоделировать метод void

Теперь давайте посмотрим, как мы можем смоделировать метод void с помощью EasyMock.

Предположим, нам нужно смоделировать метод void класса WeatherService, который берет местоположение и устанавливает минимальную и максимальную температуру:

public interface WeatherService {
    void populateTemperature(Location location);
}

4.1. Создание макета объекта

Давайте начнем с создания макета для WeatherService:

@Mock
private WeatherService mockWeatherService;

Здесь мы сделали это, используя аннотацию EasyMock @Mock. Но мы можем сделать это и с помощью метода EasyMock.mock().

Далее мы запишем ожидаемые взаимодействия с моком, вызвав populateTemperature():

mockWeatherService.populateTemperature(EasyMock.anyObject(Location.class));

Теперь, если мы не хотим имитировать обработку этого метода, этого вызова достаточно, чтобы имитировать метод.

4.2. Генерация исключения

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

В нашем примере метод генерирует исключение ServiceUnavailableException:

EasyMock.expectLastCall().andThrow(new ServiceUnavailableException());

Как показано выше, это включает в себя простой вызов метода andThrow(Throwable).

4.3. Моделирование поведения метода

Как упоминалось ранее, иногда нам может понадобиться смоделировать поведение метода void.

В нашем случае это будет включать в себя заполнение минимальной и максимальной температуры переданных местоположений:

EasyMock.expectLastCall()
  .andAnswer(() -> {
      Location passedLocation = (Location) EasyMock.getCurrentArguments()[0];
      passedLocation.setMaximumTemparature(new BigDecimal(MAX_TEMP));
      passedLocation.setMinimumTemperature(new BigDecimal(MAX_TEMP - 10));
      return null;
  });

Здесь мы использовали метод andAnswer(IAnswer) для определения поведения метода populateTemperature(), когда называется. Затем мы использовали метод EasyMock.getCurrentArguments(), который возвращает аргументы, переданные фиктивному методу, для изменения переданных местоположений.

Обратите внимание, что в конце мы вернули null. Это потому, что мы издеваемся над методом void.

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

4.4. Воспроизведение фиктивного метода

Наконец, мы будем использовать метод EasyMock.replay() для изменения макета в режим «повторного воспроизведения», чтобы записанные действия можно было воспроизвести при вызове:

EasyMock.replay(mockWeatherService);

Следовательно, когда мы вызываем тестовый метод, должно быть выполнено определенное пользовательское поведение.

5. Заключение

В этом уроке мы увидели, как имитировать методы void с помощью EasyMock.

И, конечно же, код, использованный в этой статье, можно найти на GitHub.