Как проверить, что определенный метод не был вызван с помощью Mockito?

627

Как проверить, что метод не вызывается на зависимости объекта?

Например:

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??**
    }
}
beluchin
источник

Ответы:

1091

Еще более значимым:

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

// ...

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

Документация по этой функции есть в §4 «Проверка точного количества вызовов / по крайней мере х / никогда» , и neverJavadoc здесь .

Brice
источник
144
Использование never- лучший и самый специфический способ, но если вам нужно проверить весь фиктивный объект, также рассмотрите verifyZeroInteractions(mockObject)или verifyNoMoreInteractions(mockObject).
Джефф Боуман
Что делать, если какой-то метод является частным ??
Sumit Kumar Saha
1
Тогда вы не можете высмеять его в первую очередь (с помощью Mockito);) PowerMock позволяет это сделать, но его сложнее настроить. Или, если вы владеете кодом, вы ослабляете видимость упаковки.
Брайс
2
С 3.0.1 verifyZeroInteractionsустарела. verifyNoInteractions это предложенная альтернатива. Версия Mockito во время этого комментария является 3.3.3
ВКБ
109

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

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

beluchin
источник
11
public static VerificationMode never () {время возврата (0); }
gbero
3
never()не является значительно более читабельным, чем times(0). Но существование neverдействительно увеличивает когнитивную нагрузку и делает систему мокито более сложной для понимания и запоминания того, как ее использовать. Так что действительно mockito не должен был быть включен neverв их API, это не стоит ментальных затрат.
BT
Вопрос: проверяет ли эта форма, что она someMethodбыла вызвана 0 раз, или она только проверяет, что 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)
fl0w
источник
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);
}

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

Ujjwal
источник