Как я могу использовать инъекцию с Mockito и JUnit 5?
В JUnit4 я могу просто использовать @RunWith(MockitoJUnitRunner.class)
аннотацию. В JUnit5 нет @RunWith
аннотации?
Как я могу использовать инъекцию с Mockito и JUnit 5?
В JUnit4 я могу просто использовать @RunWith(MockitoJUnitRunner.class)
аннотацию. В JUnit5 нет @RunWith
аннотации?
Ответы:
Есть разные способы использования Mockito - я рассмотрю их один за другим.
Создание макетов вручную с помощью Mockito::mock
работает независимо от версии JUnit (или тестовой среды в этом отношении).
Использование @Mock -annotation и соответствующий вызов MockitoAnnotations::initMocks
для создания издевается работает независимо от версии JUnit (или тестовой базы по этому вопросу , но Java 9 может помешать здесь, в зависимости от того, заканчивается ли тестовый код в модуле или нет).
JUnit 5 имеет мощную модель расширения, и Mockito недавно опубликовал ее под идентификатором группы / артефакта org.mockito : mockito-junit-jupiter .
Вы можете применить расширение, добавив @ExtendWith(MockitoExtension.class)
его в тестовый класс и пометив имитируемые поля с помощью @Mock
. Из MockitoExtension
JavaDoc:
@ExtendWith(MockitoExtension.class)
public class ExampleTest {
@Mock
private List list;
@Test
public void shouldDoSomething() {
list.add(100);
}
}
Документация MockitoExtension описывает другие способы создания экземпляров моков, например, с помощью внедрения конструктора (если вы rpefer конечные поля в тестовых классах).
Правила и бегуны JUnit 4 не работают в JUnit 5, поэтому бегункиMockitoRule
и Mockito использовать нельзя.
@Test
быть общедоступным или достаточно "закрытым"?
Используйте Mockito's MockitoExtension
. Расширение содержится в новом артефакте mockito-junit-jupiter
:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.23.4</version>
<scope>test</scope>
</dependency>
Это позволяет вам писать тесты, как в JUnit 4:
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
@ExtendWith(MockitoExtension.class)
class MyTest {
@Mock
private Foo foo;
@InjectMocks
private Bar bar; // constructor injection
...
}
@ExtendWith(MockitoExtension.class)
эквивалент @RunWith(MockitoJUnitRunner.class)
JUnit4
Есть разные способы сделать, но более чистый способ, который также уважает философию JUnit 5, - это создание org.junit.jupiter.api.extension.Extension
для Mockito.
1) Создание макетов вручную лишает возможности дополнительных проверок Mockito, чтобы убедиться, что вы правильно используете фреймворк.
2) Вызов MockitoAnnotations.initMocks(this)
каждого тестового класса - это шаблонный код, которого мы могли бы избежать.
И создание такой настройки в абстрактном классе тоже не лучшее решение.
Он связывает все тестовые классы с базовым классом.
Если по уважительным причинам вам потребуется новый базовый тестовый класс, вы закончите с трехуровневой иерархией классов. Пожалуйста, избегайте этого.
3) Правила тестирования - это специфика JUnit 4.
Даже не думай об этом.
И в документации об этом ясно сказано:
Однако, если вы намереваетесь разработать новое расширение для JUnit 5, используйте новую модель расширения JUnit Jupiter вместо модели JUnit 4 на основе правил.
4) Test Runner на самом деле не способ расширения JUnit 5 framework.
JUnit 5 упростил аду исполнителей JUnit 4, предоставив модель расширения для написания тестов благодаря JUnit 5 Extensions.
Даже не думай об этом.
Так что пользуйтесь org.junit.jupiter.api.extension.Extension
дорогой.
РЕДАКТИРОВАТЬ: На самом деле Mockito связывает расширение jupiter: mockito-junit-jupiter
Тогда очень просто использовать:
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class FooTest {
...
}
Вот дополнение к отличному ответу Джонатана.
Путем добавления mockito-junit-jupiter
артефакта в качестве зависимости использование @ExtendWith(MockitoExtension.class)
привело к следующему исключению при выполнении теста:
java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation (Ljava / util / Необязательно; Ljava / lang / Class;) Ljava / util / Необязательно;
Проблема в том, что это mockito-junit-jupiter
зависит от двух независимых библиотек. Например для mockito-junit-jupiter:2.19.0
:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.19.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.1.0</version>
<scope>runtime</scope>
</dependency>
Проблема была в том, что я использовал junit-jupiter-api:5.0.1
.
Так , как junit-jupiter-api
движется по- прежнему часто с точки зрения API, убедитесь , что вы зависите от одной и той же версии , junit-jupiter-api
что mockito-junit-jupiter
зависит от.
mockito-junit-jupiter
тянет нужную версию junit-jupiter-api
?
mockito-junit-jupiter:2.19.0
. Хотя версии JUnit Jupiter начинаются с 5
. mockito-junit-jupiter должен был указать в своем идентификаторе артефакта две вещи (версию Mockito и версию JUnit Jupiter), чтобы было понятнее. Например, mockito-junit-jupiter-5.1:2.19.0
чтобы передать, что библиотека разработана для JUnit Jupiter 5.1.
MockitoExtension
не существует в mockito-core
версии 3.0.0.
mockito-junit-jupiter
Вы должны использовать новую @ExtendWith
аннотацию.
К сожалению, расширения еще нет. На github вы можете увидеть бета-версию расширения. в качестве примера демонстрационного теста .