Як переконатися, що конкретний метод не викликався за допомогою Mockito?


625

Як переконатися, що метод не викликається залежністю об'єкта?

Наприклад:

public interface Dependency {
    void someMethod();
}

public class Foo {
    public bar(final Dependency d) {
        ...
    }
}

За допомогою тесту Foo:

public class FooTest {
    @Test
    public void dependencyIsNotCalled() {
        final Foo foo = new Foo(...);
        final Dependency dependency = mock(Dependency.class);
        foo.bar(dependency);
        **// verify here that someMethod was not called??**
    }
}

Відповіді:


1087

Ще змістовніше:

import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

// ...

verify(dependency, never()).someMethod();

Документація цієї функції є там §4 "Перевірка точної кількості викликів / принаймні х / ніколи" , і neverjavadoc знаходиться тут .


144
Використання never- найкращий і найбільш конкретний спосіб, але якщо вам потрібно перевірити цілий макетний об’єкт, також врахуйте verifyZeroInteractions(mockObject)або verifyNoMoreInteractions(mockObject).
Джефф Боуман

що робити, якщо деякийМетод приватний ??
Суміт Кумар Саха

1
Тоді ви не можете знущатися над цим в першу чергу (з Mockito);) PowerMock дозволяє до цього, але це складніше налаштувати. Або якщо у вас є право власності на код, ви послабите видимість упаковки.
Бріс

2
З verifyZeroInteractionsмоменту застарілості 3.0.1 . verifyNoInteractions є запропонованою альтернативою. Версія Mockito на момент отримання цього коментаря - 3.3.3
VKB

108

використовувати другий аргумент Mockito.verifyметоду, як у:

verify(dependency, Mockito.times(0)).someMethod()


11
загальнодоступна статична VerificationMode never () {час повернення (0); }
gbero

3
never()суттєво не читабельніше, ніж times(0). Але існування neverдійсно збільшує когнітивне навантаження і робить систему мокіто важче зрозуміти і запам'ятати, як користуватися. Тож насправді мокіто не повинно було включатись neverу свій API, це не варто ментальних витрат.
BT

Запитання: чи підтверджує ця форма someMethod0 разів, чи вона лише перевіряє, що someMethodніколи не викликалася нульовими аргументами?
BT

@BT - я думаю, він підтверджує, що someMethodаргументи з нулем називали нульовими разів - не перевірені.
белучин

18

Як більш загальну схему, яку слід дотримуватися, я схильний використовувати @Afterблок в тесті:

@After
public void after() {
    verifyNoMoreInteractions(<your mock1>, <your mock2>...);
}

Тоді тест може вільно перевірити лише те, що слід викликати.

Крім того, я виявив, що часто забував перевірити на "відсутність взаємодій", аби згодом виявити, що називаються речі, яких не повинно було бути.

Тому я вважаю цю модель корисною для лову всіх несподіваних дзвінків, які не були спеціально підтверджені.


9
Документація Mockito зазначає, що цим шаблоном не слід зловживати - "Слово попередження: Деякі користувачі, які зробили багато класичного, глузування з очікуванням запуску, перевіряють, як правило, дуже часто, навіть у кожному методі тестування, використовують verifyNoMoreInteractions (). VerifyNoMoreInteractions () не рекомендується використовувати в кожному методі тестування. verifyNoMoreInteractions () - це зручне твердження з набору інструментів тестування взаємодії. Використовуйте його лише тоді, коли це доречно. Зловживання ним призводить до завищених, менш рентабельних тестів. " Дивіться тут
Чаді

2
"Використовуйте його лише тоді, коли це доречно" Я відчуваю, що це завжди актуально. Я не розглядаю цей зразок як зловживання: як я вже сказав, він вважає, що "називалося те, чого не повинно було бути". Для мене це важлива перевірка: якщо щось викликає сховище, яке воно не повинно використовувати, я хочу знати про це! Якщо тільки немає іншого способу перевірити це без використання verifyNoMoreInteractions? Інші відповіді тут покладаються на тест-письменника, явно пам'ятаючи, щоб перерахувати ці перевірки: це занадто помилка, схильна до моєї книги.
Девід Лаванда

2
Я бачив цей коментар, але також відчував, що міркування не є переконливими. Я хотів би прочитати більше про те, чому це не рекомендується.
tobinibot

2
@tobinibot Оскільки ідея тестування підрозділу полягає у підтвердженні контракту. Більшість контрактів, як правило, не передбачає, скільки разів викликається якийсь інший метод, а швидше, що передача відомих параметрів призводить до відомої відповіді. Використовуючи більше ніяких взаємодій, ви в основному перевіряєте реалізацію по черзі, що робить рефакторинг та реалізацію нудними. Що не сенс тестування одиниць.
Ендрю Т Фіннелл

8

Перш за все: ви завжди повинні імпортувати mockito static, таким чином код буде набагато більш читабельним (та інтуїтивно зрозумілим):

import static org.mockito.Mockito.*;

Насправді існує багато способів цього досягти, однак використовувати (можливо, чистіше)

verify(yourMock, times(0)).someMethod();

метод у всіх тестах, коли в інших тестах ви використовуєте його для ствердження певної кількості таких виконань:

verify(yourMock, times(5)).someMethod();

Альтернативи:

verify(yourMock, never()).someMethod();

Крім того, коли ви дійсно хочете переконатися, що певний насмішений Об'єкт насправді НЕ викликається - ви можете використовувати:

verifyZeroInteractions(yourMock)

7

І внутрішній, verifyNoMoreInteractions()і verifyZeroInteractions()метод мають однакову реалізацію, як:

public static transient void verifyNoMoreInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

public static transient void verifyZeroInteractions(Object mocks[])
{
    MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}

тому ми можемо використовувати будь-який з них на макетному об’єкті або масиві макетних об’єктів, щоб перевірити, чи не було викликано жодних методів за допомогою макетних об’єктів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.