@RunWith (MockitoJUnitRunner.class) против MockitoAnnotations.initMocks (это)

При написании нового теста jUnit4 мне интересно, использовать ли @RunWith(MockitoJUnitRunner.class) или MockitoAnnotations.initMocks(this).

Я создал новый тест, и мастер автоматически сгенерировал тест с помощью Runner. В документации Javadocs для MockitoJUnitRunner указано следующее:

Совместимый с JUnit 4.4 и выше, этот бегун добавляет следующее поведение:

Инициализирует макеты, аннотированные с помощью Mock, поэтому явное использование MockitoAnnotations.initMocks (Object) не требуется. Моки инициализируются перед каждым методом тестирования. Проверяет использование фреймворка после каждого метода тестирования.

Мне не ясно, имеет ли использование Runner какое-либо преимущество перед методом initMocks(), который я использовал в прошлом.


person OceanBlue    schedule 29.05.2012    source источник


Ответы (2)


MockitoJUnitRunner дает вам автоматическое подтверждение использования фреймворка, а также автоматическое initMocks().

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

  • Вы вызываете статический метод when, но не завершаете заглушку соответствующими thenReturn, thenThrow или then. (Ошибка 1 в приведенном ниже коде)

  • Вы вызываете verify как имитацию, но забываете предоставить вызов метода, который вы пытаетесь проверить. (Ошибка 2 в приведенном ниже коде)

  • Вы вызываете метод when после doReturn, doThrow или doAnswer и передаете имитацию, но забываете предоставить метод, который пытаетесь заглушить. (Ошибка 3 в приведенном ниже коде)

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

  • в том же методе тестирования (например, ошибка 1 ниже),
  • в следующем методе тестирования (например, ошибка 2 ниже),
  • в следующем тестовом классе.

Если они возникнут в последнем запущенном вами тесте (например, ошибка 3 ниже), о них вообще не будет сообщено.

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

@Test
public void test1() {

    // ERROR 1
    // This compiles and runs, but it's an invalid use of the framework because 
    // Mockito is still waiting to find out what it should do when myMethod is called.
    // But Mockito can't report it yet, because the call to thenReturn might 
    // be yet to happen.
    when(myMock.method1());

    doSomeTestingStuff();

    // ERROR 1 is reported on the following line, even though it's not the line with
    // the error.
    verify(myMock).method2();

}

@Test
public void test2() {

    doSomeTestingStuff();

    // ERROR 2
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call to verify.  But Mockito can't report 
    // it yet, because the call to the method that's being verified might 
    // be yet to happen.
    verify(myMock);
}

@Test
public void test3() {

    // ERROR 2 is reported on the following line, even though it's not even in 
    // the same test as the error.
    doReturn("Hello").when(myMock).method1();


    // ERROR 3
    // This compiles and runs, but it's an invalid use of the framework because
    // Mockito doesn't know what method call is being stubbed.  But Mockito can't 
    // report it yet, because the call to the method that's being stubbed might 
    // be yet to happen.

    doReturn("World").when(myMock);

    doSomeTestingStuff(); 

    //  ERROR 3 is never reported, because there are no more Mockito calls. 
}

Когда я впервые написал этот ответ более пяти лет назад, я написал

Поэтому я бы рекомендовал использовать MockitoJUnitRunner везде, где это возможно. Однако, как правильно заметил Томаш Нуркевич, вы не можете использовать его, если вам нужен другой бегун JUnit, такой как Spring.

Моя рекомендация изменилась. Команда Mockito добавила новую функцию с тех пор, как я впервые написал этот ответ. Это правило JUnit, которое выполняет ту же функцию, что и MockitoJUnitRunner. Но так лучше, потому что это не исключает возможности использования других бегунов.

Включают

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

в вашем тестовом классе. Это инициализирует макеты и автоматизирует проверку фреймворка; прямо как MockitoJUnitRunner. Но теперь вы также можете использовать SpringJUnit4ClassRunner или любой другой JUnitRunner. Начиная с Mockito 2.1.0, есть дополнительные параметры, которые точно определяют, о каких проблемах следует сообщать.

person Dawood ibn Kareem    schedule 30.05.2012
comment
Я определенно не могу сказать, что они такие же. в одном тестовом случае установка junit runner для меня не работает и не вводит мои макеты должным образом, если я не выполняю настройку initMocks - person dtc; 24.06.2016
comment
Мы используем testng 6.8.8 + mockito 1.10.19 и, очевидно, мы не можем использовать MockitoJUnitRunner, но структура проверки все еще работает! И он работает точно так же, как @David Wallace. Кто-нибудь может объяснить? Это потому, что у нас все еще есть обратные вызовы @ Before * и MockitoAnnotations.initMocks (this)? - person yuranos; 08.12.2016
comment
@ yuranos87 Похоже, вам следует задать новый вопрос. Не забудьте включить свой код, когда вы это сделаете - бессмысленно спрашивать, почему этот код выполняет XYZ, если вы его не показываете. - person Dawood ibn Kareem; 08.12.2016
comment
@DavidWallace, пожалуйста: stackoverflow.com/questions/41045467/ - person yuranos; 08.12.2016
comment
использование решения TestRunner намного превосходит @Rule - person Rule; 27.11.2017
comment
Это мой любимый ответ о Mockito из закладок. Пора обновить и включить @ExtendWith для JUnit5? - person alexandroid; 05.12.2019
comment
@alexandroid Мое лучшее предложение - написать свой собственный ответ, используя @ExtendWith. На самом деле я не знаю об этом. Самое замечательное в Stack Overflow заключается в том, что на такой вопрос вы можете получить несколько правильных ответов. - person Dawood ibn Kareem; 05.12.2019

Использование runner позволяет сэкономить немного кода (нет необходимости в методе @Before). С другой стороны, использование бегуна иногда невозможно, т. Е. Когда вы уже используете его, например _ 2_.

Вот и все. Это просто вопрос предпочтения.

person Tomasz Nurkiewicz    schedule 29.05.2012
comment
Помимо строки initMocks (), метод @Before все равно понадобится для любой другой настройки, верно? - person OceanBlue; 30.05.2012
comment
@OceanBlue: Конечно, если ваш метод @Before содержал что-либо, кроме initMocks(), вы должны сохранить его после перехода на runner. - person Tomasz Nurkiewicz; 30.05.2012
comment
Ответ Дэвида Уоллеса о проверке фреймворка полностью отвечает на мой вопрос, поэтому я принял его, но +1 за указание на то, что этот бегун не может использоваться с другим, например Spring. Спасибо! - person OceanBlue; 30.05.2012
comment
Я использую Spring Boot и могу сказать, что SpringJUnit4ClassRunner автоматически инициализирует для меня mock'ы. Однако я не знаю, что такое обычная весна. - person gustavohenke; 18.11.2016