@RunWith(MockitoJUnitRunner.class) vs MockitoAnnotations.initMocks(это)

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

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

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

Инициализирует mocks, аннотированный Mock, так что явное использование MockitoAnnotations.initMocks(Object) не требуется. Mocks инициализируется перед каждым методом тестирования. проверяет использование рамок после каждого тестового метода.

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

Любые мысли или ссылки будут оценены!

Ответ 1

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

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

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

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

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

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

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

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

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

@Test
public void test1() {

    // ERROR 1
    // This compiles and runs, but it 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 not the line with
    // the error.
    verify(myMock).method2();

}

@Test
public void test2() {

    doSomeTestingStuff();

    // ERROR 2
    // This compiles and runs, but it 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 being verified might 
    // be yet to happen.
    verify(myMock);
}

@Test
public void test3() {

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


    // ERROR 3
    // This compiles and runs, but it 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 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();

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

Ответ 2

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

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