«1. Обзор

В этом кратком руководстве мы узнаем об исключении Mockito UnnecessaryStubbingException. Это исключение является одним из распространенных исключений, с которыми мы, вероятно, столкнемся при неправильном использовании заглушек.

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

Чтобы узнать больше о тестировании с помощью Mockito, ознакомьтесь с нашей обширной серией статей о Mockito.

2. Строгая заглушка

В версии 1.x Mockito можно было настраивать макеты и взаимодействовать с ними без каких-либо ограничений. Это означало, что со временем тесты часто становились слишком сложными, а временами их было труднее отлаживать.

Начиная с версии 2.+, Mockito вводит новые функции, которые подталкивают фреймворк к «строгости». Основные цели, стоящие за этим:

    Обнаружение неиспользуемых заглушек в тестовом коде. Сокращение дублирования тестового кода и ненужного тестового кода. Содействие более чистым тестам путем удаления «мертвого» кода. более чистые тесты, исключая ненужный тестовый код. Они также помогают избежать ошибок копирования и вставки, а также других упущений разработчиков.

Подводя итог, строгая заглушка сообщает о ненужных заглушках, обнаруживает несоответствие аргументов заглушки и делает наши тесты более СУХИМИ (не повторяйтесь). Это облегчает чистую и поддерживаемую кодовую базу.

2.1. Настройка строгих заглушек

Начиная с Mockito 2.+, строгая заглушка используется по умолчанию при инициализации наших макетов с помощью любого из:

MockitoJUnitRunner MockitoJUnit.rule()

    Mockito настоятельно рекомендует использовать любой из вышеперечисленных. Однако есть еще один способ включить строгую заглушку в наших тестах, когда мы не используем правило или бегун Mockito:

И последнее важное замечание: в Mockito 3.0 все заглушки будут: «строгие» и проверены по умолчанию.

Mockito.mockitoSession()
  .initMocks(this)
  .strictness(Strictness.STRICT_STUBS)
  .startMocking();

3. Пример исключения UnnecessaryStubbingException

Проще говоря, ненужная заглушка — это заглушенный вызов метода, который так и не был реализован во время выполнения теста.

Давайте рассмотрим простой пример:

Когда мы запустим этот модульный тест, Mockito обнаружит неиспользуемую заглушку и выдаст исключение UnnecessaryStubbingException:

@Test
public void givenUnusedStub_whenInvokingGetThenThrowUnnecessaryStubbingException() {
    when(mockList.add("one")).thenReturn(true); // this won't get called
    when(mockList.get(anyInt())).thenReturn("hello");
    assertEquals("List should contain hello", "hello", mockList.get(1));
}

К счастью, из ошибки все ясно. напишите в чем тут проблема. Мы также можем видеть, что сообщение об исключении даже указывает нам на точную строку, которая вызывает ошибку.

org.mockito.exceptions.misusing.UnnecessaryStubbingException: 
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at com.baeldung.mockito.misusing.MockitoUnecessaryStubUnitTest.givenUnusedStub_whenInvokingGetThenThrowUnnecessaryStubbingException(MockitoUnecessaryStubUnitTest.java:37)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.

Почему это происходит? Ну, во-первых, когда вызов настраивает наш макет так, чтобы он возвращал true, когда мы вызываем метод добавления с аргументом «один». Однако затем мы не вызываем этот метод во время выполнения остальной части модульного теста.

Mockito говорит нам, что наша первая строка when избыточна и, возможно, мы допустили ошибку при настройке наших заглушек.

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

4. Обход строгих заглушек

Наконец, давайте посмотрим, как обойти строгие заглушки. Это также известно как снисходительное заглушение.

Иногда нам нужно настроить определенные заглушки, чтобы они были мягкими, сохраняя при этом все остальные заглушки и имитации, чтобы использовать строгие заглушки:

В приведенном выше примере мы используем статический метод Mockito.lenient(), чтобы включить снисходительное заглушение метода добавления нашего фиктивного списка.

@Test
public void givenLenientdStub_whenInvokingGetThenThrowUnnecessaryStubbingException() {
    lenient().when(mockList.add("one")).thenReturn(true);
    when(mockList.get(anyInt())).thenReturn("hello");
    assertEquals("List should contain hello", "hello", mockList.get(1));
}

Мягкие заглушки обходят правила проверки «строгих заглушек». Например, если заглушка объявлена ​​как мягкая, она не будет проверяться на возможные проблемы с заглушкой, такие как ненужная заглушка, описанная ранее.

5. Заключение

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

«Затем мы рассмотрели пример исключения UnnecessaryStubbingException, прежде чем закончить примером того, как включить мягкую заглушку в наших тестах.

Как всегда, полный исходный код статьи доступен на GitHub.

«