Как разрешить исключение Unneccessary Stubbing

Мой код выглядит следующим образом:

@RunWith(MockitoJUnitRunner.class)
public class MyClass {

    private static final String code ="Test";

    @Mock
     private MyClassDAO dao;

    @InjectMocks
     private MyClassService Service = new MyClassServiceImpl();

    @Test
     public void testDoSearch() throws Exception {
         final String METHOD_NAME = logger.getName().concat(".testDoSearchEcRcfInspections()");
         CriteriaDTO dto = new CriteriaDTO();
         dto.setCode(code);
         inspectionService.searchEcRcfInspections(dto);
         List<SearchCriteriaDTO> summaryList = new ArrayList<SearchCriteriaDTO>();
         inspectionsSummaryList.add(dto);
         when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
         verify(dao).doSearchInspections(dto);

      }
}

Я получаю ниже исключения

org.mockito.exceptions.misusing.UnnecessaryStubbingException: 
Unnecessary stubbings detected in test class: Test
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at service.Test.testDoSearch(Test.java:72)
Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class.
  at org.mockito.internal.exceptions.Reporter.formatUnncessaryStubbingException(Reporter.java:838)
  at org.mockito.internal.junit.UnnecessaryStubbingsReporter.validateUnusedStubs(UnnecessaryStubbingsReporter.java:34)
  at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:49)
  at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:103)
  at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
  at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Пожалуйста, помогите мне, как разрешить

Ответ 1

Замените @RunWith(MockitoJUnitRunner.class) на @RunWith(MockitoJUnitRunner.Silent.class).

Ответ 2

Сначала вы должны проверить свою тестовую логику. Обычно бывает 3 случая. Во-первых, вы издеваетесь над неправильным методом (вы сделали опечатку или кто-то изменил проверенный код, чтобы смоделированный метод больше не использовался). Во-вторых, ваш тест не пройден до вызова этого метода. В-третьих, ваша логика ошибается, если где-то в коде ветвь /switch, так что смоделированный метод не вызывается.

Если это первый случай, вы всегда хотите сменить метод, который используется в коде. Со вторым и третьим это зависит. Обычно вы должны просто удалить этот макет, если он бесполезен. Но иногда в параметризованных тестах есть определенные случаи, которые должны идти по другому пути или провалиться раньше. Затем вы можете разделить этот тест на два или более отдельных, но это не всегда хорошо выглядит. 3 метода тестирования с возможно тремя поставщиками аргументов могут сделать ваш тест нечитаемым. В этом случае для JUnit 4 вы исключаете это исключение либо

@RunWith(MockitoJUnitRunner.Silent.class) 

аннотации или если вы используете подход правила

@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.LENIENT);

или (такое же поведение)

@Rule
public MockitoRule rule = MockitoJUnit.rule().silent();

Для тестов JUnit 5 вы можете mockito-junit-jupiter это исключение, используя аннотацию, предоставленную в mockito-junit-jupiter.

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class JUnit5MockitoTest {
}

Ответ 3

 when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
 verify(dao).doSearchInspections(dto);

when здесь настраивает ваш макет, чтобы что-то сделать. Тем не менее, вы больше не используете этот макет после этой строки (помимо создания verify). Mockito предупреждает вас, что строка when не имеет смысла. Возможно, вы сделали логическую ошибку?

Ответ 4

Безмолвие не является решением. Вы должны исправить свой макет в вашем тесте. Смотрите официальную документацию здесь.

Ненужные заглушки - это вызовы методов-заглушек, которые никогда не были реализованы во время выполнения теста (см. Также MockitoHint), пример:

//code under test:
 ...
 String result = translator.translate("one")
 ...

 //test:
 ...
 when(translator.translate("one")).thenReturn("jeden"); // <- stubbing realized during code execution
 when(translator.translate("two")).thenReturn("dwa"); // <- stubbing never realized
 ...

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

Чтобы узнать больше об обнаружении неиспользованных заглушек, см. MockitoHint.

Ответ 5

Для меня ни предложения @Rule ни @RunWith(MockitoJUnitRunner.Silent.class) сработали. Это был унаследованный проект, в котором мы обновились до версии 2.23.0.

Мы могли бы избавиться от UnnecessaryStubbingException, используя:

Mockito.lenient().when(mockedService.getUserById(any())).thenReturn(new User());

вместо:

when(mockedService.getUserById(any())).thenReturn(new User());

Само собой разумеется, что вы должны смотреть на тестовый код, но нам нужно было скомпилировать материал и запустить тесты в первую очередь;)

Ответ 6

Глядя на часть трассировки вашего стека, похоже, что вы усекаете dao.doSearch() в другом месте. Больше похоже на повторное создание заглушек того же метода.

Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at service.Test.testDoSearch(Test.java:72)
Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class.

Рассмотрим приведенный ниже тестовый класс:

@RunWith(MockitoJUnitRunner.class)
public class SomeTest {
    @Mock
    Service1 svc1Mock1;

    @Mock
    Service2 svc2Mock2;

    @InjectMock
    TestClass class;

    //Assume you have many dependencies and you want to set up all the stubs 
    //in one place assuming that all your tests need these stubs.

    //I know that any initialization code for the test can/should be in a 
    //@Before method. Lets assume there is another method just to create 
    //your stubs.

    public void setUpRequiredStubs() {
        when(svc1Mock1.someMethod(any(), any())).thenReturn(something));
        when(svc2Mock2.someOtherMethod(any())).thenReturn(somethingElse);
    }

    @Test
    public void methodUnderTest_StateUnderTest_ExpectedBehavior() {
        // You forget that you defined the stub for svcMock1.someMethod or 
        //thought you could redefine it. Well you cannot. That going to be 
        //a problem and would throw your UnnecessaryStubbingException.
       when(svc1Mock1.someMethod(any(),any())).thenReturn(anyThing);//ERROR!
       setUpRequiredStubs();
    }
}

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

Ответ 7

Если вы используете этот стиль вместо:

@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

замените его на:

@Rule
public MockitoRule rule = MockitoJUnit.rule().silent();

Ответ 8

У меня был UnnecessaryStubbingException, когда я пытался использовать методы when на шпионском объекте. Mockito.lenient() заставил замолчать исключение, но результаты теста были неверными.

В случае объектов Spy необходимо вызывать методы напрямую.

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)
class ArithmTest {

    @Spy
    private Arithm arithm;

    @Test
    void testAddition() {

        int res = arithm.add(2, 5);

        // doReturn(7).when(arithm).add(2, 5);
        assertEquals(res, 7);
    }
}

Ответ 9

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

https://gist.github.com/cueo/da1ca49e92679ac49f808c7ef594e75b

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

Ответ 10

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

Вот как это было, когда пришла ошибка:

@Test
fun 'should return error when item list is empty for getStockAvailability'() {
    doAnswer(
        Answer<Void> { invocation ->
            val callback =
                invocation.arguments[1] as GetStockApiCallback<StockResultViewState.Idle, StockResultViewState.Error>
            callback.onApiCallError(stockResultViewStateError)
            null
        }
    ).whenever(stockViewModelTest)
        .getStockAvailability(listOf(), getStocksApiCallBack)
}

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

изменения сделаны как ниже stockViewModelTest.getStockAvailability(listOf(), getStocksApiCallBack)

@Test
fun 'should return error when item list is empty for getStockAvailability'() {
    doAnswer(
        Answer<Void> { invocation ->
            val callback =
                invocation.arguments[1] as GetStockApiCallback<StockResultViewState.Idle, StockResultViewState.Error>
            callback.onApiCallError(stockResultViewStateError)
            null
        }
    ).whenever(stockViewModelTest)
        .getStockAvailability(listOf(), getStocksApiCallBack)
    //called the actual method here
    stockViewModelTest.getStockAvailability(listOf(), getStocksApiCallBack)
}

это работает сейчас.

Ответ 11

Я столкнулся с этой проблемой при обновлении до mockito-core: 2.18.0 и powermock-module-junit4: 2.0.0-beta.5

Вышеуказанные ответы помогли мне. Наряду с этим, убедитесь, что вы изменили

Старый код:

import org.mockito.runners.MockitoJUnitRunner;

Новый код:

import org.mockito.junit.MockitoJUnitRunner;