@RunWith (MockitoJUnitRunner.class) проти MockitoAnnotations.initMocks (це)


118

Під час написання нового тесту jUnit4 мені цікаво, чи використовувати @RunWith (MockitoJUnitRunner.class) або MockitoAnnotations.initMocks (це) .

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

Сумісний з JUnit 4.4 та новішими версіями, цей бігун додає наступної поведінки:

Ініціалізує макети, зазначаються з Mock, так що явне використання MockitoAnnotations.initMocks (Object) не є необхідним. Макети ініціалізуються перед кожним методом тестування. перевіряє використання рамок після кожного методу тестування.

Мені не зрозуміло, чи має використання Runner якусь перевагу перед методом initMocks (), яким я користувався в минулому.

Будь-які думки чи посилання будуть вдячні!

Відповіді:


147

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, наприклад весняний.

Зараз моя рекомендація змінилася. Команда Mockito додала нову функцію, оскільки я вперше написала цю відповідь. Це правило JUnit, яке виконує точно таку ж функцію, як і MockitoJUnitRunner. Але це краще, тому що це не виключає використання інших бігунів.

Включати

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

у вашому тестовому класі. Це ініціалізує макети та автоматизує перевірку фреймворку; так само, як MockitoJUnitRunnerце робить. Але тепер ви можете також використовувати SpringJUnit4ClassRunnerбудь-який інший JUnitRunner. Починаючи з Mockito 2.1.0, є додаткові параметри, які точно контролюють, про які проблеми повідомляються.


я точно не можу сказати, що вони однакові. в одному тестовому випадку, налаштування бігуна для джуніту не вдалося мені і не вводить мої глузування належним чином, якщо я не виконую налаштування
initMocks

Ми використовуємо тест 6.8.8 + mockito 1.10.19, і, очевидно, ми не можемо використовувати MockitoJUnitRunner, але система перевірки все ще працює! І працює саме так, як @David Wallace. Може хтось пояснить? Це тому, що у нас все ще є зворотні виклики @ Перед * та MockitoAnnotations.initMocks (це)?
yuranos

@ yuranos87 Здається, як щось, що вам слід задати як нове запитання. Не забудьте додати свій код, коли це робите - трохи безглуздо запитувати "чому цей код робить XYZ", якщо ви не показуєте код.
Dawood ibn Kareem

1
використання рішення TestRunner на сьогоднішній день перевершує @Rule
правило

1
@alexandroid Моя найкраща пропозиція для вас написати власну відповідь, використовуючи @ExtendWith. Це насправді не те, про що я знаю. Чудова річ про переповнення стека полягає в тому, що на подібне запитання ви можете отримати кілька правильних відповідей.
Dawood ibn Kareem

24

Використання бігуна дозволяє зберегти трохи кодування (немає необхідності в @Beforeметоді). З іншого боку, використання бігуна іноді неможливо, тобто коли ви вже використовуєте його, наприклад SpringJUnit4ClassRunner.

Це воно. Це лише питання переваги.


2
Окрім рядка initMocks (), метод @Before все ще буде потрібен для будь-якого іншого налаштування, правда?
OceanBlue

2
@OceanBlue: Звичайно, якщо ваш @Beforeметод містив що-небудь, крім initMocks()того, що ви повинні зберегти після переходу на бігун.
Томаш Нуркевич

Відповідь Девіда Уоллеса про валідацію фреймворку відповідає на моє запитання повністю, тому я прийняв це, але +1, зазначаючи, що цього бігуна не можна використовувати з іншим, як весняний. Дякую!
OceanBlue

1
Я використовую Spring Boot і можу сказати, що SpringJUnit4ClassRunnerавтоматично ініціалізує макети для мене. Я не знаю про просту Весну.
gustavohenke
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.