Как проверить, что определенный метод не был вызван с помощью 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??**
    }
}

Ответы:


1091

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

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

// ...

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

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


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


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)

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.