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

Так, цей код працюватиме, тест не впаде.

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. Метод doThrow()

Ми розібралися, як зробити, щоб метод мок-об'єкта повернув певний результат. А як зробити так, щоб він кинув певний виняток? Передати його в doReturn()?

Щоб метод не повернув, а саме викинув (throw) виняток, потрібно встановити правило за допомогою методу doThrow().

Mockito.doThrow(виняток.).when(об'єкт).ім'яМетоду();

І одразу другий варіант:

Mockito.when(об'єкт.ім'яМетоду()).thenThrow(виняток.);

Трохи очікувано, чи не так?

Ось бачиш, ти вже починаєш розумітися в цьому. Закріпимо знання прикладом:


@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() об'єкт виключення, і його буде викинуто під час виклику методу.