3.1 Метод doReturn()

А теперь будет магия…

Допустим, ты создал фейковый мок-объект, но ведь нужно чтобы он как-то работал. При вызове определенных методов делалось что-то важное или методы возвращали определенный результат. Что делать?

Библиотека Mockito позволяет добавить мок-объекту нужное поведение.

Если ты хочешь, чтобы при вызове определенного метода, мок-объект вернул определенный результат, то это “правило” можно добавить объекту с помощью кода:

Mockito.doReturn(результат).when(объект).имяМетода();

Видишь, в конце вызова метода имяМетода? На самом деле никакого вызова тут не происходит. Метод doReturn() возвращает специальный proxy-объект с помощью которого следит за вызовами методов объекта и, таким образом, идет запись правила.

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

Думаю, нужен конкретный пример. Давайте создадим мок-объект класса ArrayList и попросим его метод size() вернуть число 10. Полный вариант кода будет выглядеть так:

@ExtendWith(MockitoExtension.class)
class DoReturnTest {
    @Mock
    List mockList;

    @Test
    public void whenMockAnnotation () {
         //создаем правило: вернуть 10 при вызове метода size
        Mockito.doReturn(10).when(mockList).size();

        //тут вызывается метод и вернет 10!!
        assertEquals(10, mockList.size());
    }
}

Да, этот код будет работать, тест не упадет.

3.2 Метод when()

Есть еще один способ добавить правило поведения к мок-объекту – через вызов метода Mockito.when(). Выглядит вот так:

Mockito.when(объект.имяМетода()).thenReturn(результат);

Это такой же способ записи правила поведения мок-объекта, как и предыдущий. Сравните:

Mockito.doReturn(результат).when(объект).имяМетода();

Тут происходит абсолютно одно и то же – конструирование нового правила.

Правда первый пример имеет два минуса:

  • вызов объект.имяМетода() сильно сбивает с толку.
  • не будет работать, если метод имяМетода() возвращает void.

Ну и давайте запишем полюбившийся нам пример с помощью Mockito.when()

@ExtendWith(MockitoExtension.class)
class WhenTest {
    @Mock
    List mockList;

    @Test
    public void whenMockAnnotation() {
        //создаем правило: вернуть 10 при вызове метода size
        Mockito.when(mockList.size() ).thenReturn(10);

        //тут вызывается метод и вернет 10!!
        assertEquals(10, mockList.size());
    }
}

3.3 Метод doThrow()

Мы разобрались, как сделать так, чтобы метод мок-объекта вернул определенный результат. А как сделать так, чтобы он кинул определенное исключение? Передать его в doReturn()?

Чтобы метод не вернул, а именно выбросил (throw) исключение, нужно задать правило с помощью метода doThrow().

Mockito.doThrow(исключение.class).when(объект).имяМетода();

И сразу второй вариант:

Mockito.when(объект.имяМетода()).thenThrow(исключение.class);

Немного ожидаемо, да?

Ну вот видишь, ты уже начинаешь разбираться. Закрепим примером:

@ExtendWith(MockitoExtension.class)
class DoThrowTest {
    @Mock
    List mockList;

    @Test
    public void whenMockAnnotation() {
        Mockito.when(mockList.size() ).thenThrow(IllegalStateException.class);
        mockList.size(); //тут кинется исключение
    }
}

Если нужно выкинуть определенный объект-исключение, то воспользуйся конструкцией вида:

Mockito.doThrow(new Исключение()).when(объект).имяМетода();

Просто передай в метод doThrow() объект исключения и он будет выброшен во время вызова метода.