Як я можу використовувати ін’єкцію з Mockito та JUnit 5?
У JUnit4 я можу просто використовувати Анотацію @RunWith(MockitoJUnitRunner.class)
. У JUnit5 немає @RunWith
анотації?
Як я можу використовувати ін’єкцію з Mockito та JUnit 5?
У JUnit4 я можу просто використовувати Анотацію @RunWith(MockitoJUnitRunner.class)
. У JUnit5 немає @RunWith
анотації?
Відповіді:
Існують різні способи використання Mockito - я розгляну їх по одному.
Створення макетів вручну з Mockito::mock
творами незалежно від версії JUnit (або тестового фреймворку).
Використання @Mock -нотації та відповідного виклику to 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 описує інші способи створення екземплярів макетів, наприклад за допомогою введення конструктора (якщо ви використовуєте остаточні поля в тестових класах).
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 рівні. Будь ласка, уникайте цього.
3) Правила тестування - це специфіка JUnit 4.
Навіть не думайте про це.
І документація чітко про це говорить:
Однак, якщо ви збираєтеся розробити нове розширення для JUnit 5, будь ласка, використовуйте нову модель розширення JUnit Jupiter замість заснованої на правилах моделі JUnit 4.
4) Test Runner насправді не спосіб розширити фреймворк JUnit 5.
JUnit 5 спростив пекло бігунів JUnit 4, надавши модель розширення для написання тестів завдяки JUnit 5 Extensions.
Навіть не думайте про це.
Тож віддайте перевагу org.junit.jupiter.api.extension.Extension
шляху.
EDIT: Власне, Mockito поєднує розширення юпітера: 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 ви можете побачити бета-версію розширення. як приклад демонстраційного тесту .