Як користуватися Mockito з JUnit5


103

Як я можу використовувати ін’єкцію з Mockito та JUnit 5?

У JUnit4 я можу просто використовувати Анотацію @RunWith(MockitoJUnitRunner.class). У JUnit5 немає @RunWithанотації?

Відповіді:


144

Існують різні способи використання Mockito - я розгляну їх по одному.

Вручну

Створення макетів вручну з Mockito::mockтворами незалежно від версії JUnit (або тестового фреймворку).

На основі анотацій

Використання @Mock -нотації та відповідного виклику to MockitoAnnotations::initMocks для створення макетів працює незалежно від версії JUnit (або тестового фреймворку, але Java 9 може тут заважати, залежно від того, чи тестовий код потрапляє в модуль чи ні).

Розширення Mockito

JUnit 5 має потужну модель розширення, і Mockito нещодавно опублікував її під ідентифікатором групи / артефакту org.mockito : mockito-junit-jupiter .

Ви можете застосувати розширення, додавши @ExtendWith(MockitoExtension.class)до тестового класу та анотуючи знущані поля з @Mock. З MockitoExtensionJavaDoc:

@ExtendWith(MockitoExtension.class)
public class ExampleTest {

    @Mock
    private List list;

    @Test
    public void shouldDoSomething() {
        list.add(100);
    }

}

Документація MockitoExtension описує інші способи створення екземплярів макетів, наприклад за допомогою введення конструктора (якщо ви використовуєте остаточні поля в тестових класах).

Без правил, без бігунів

JUnit 4 правила і бігуни не працюють в JUnit 5, так MockitoRuleі бігун Mockito не може бути використаний.


6
Зараз існує офіційне розширення Mockito Junit5, що еквівалентно MockitoJUnitRunner -> mockito-junit-jupiter
dan carter

Коли було випущено офіційне розширення для Mockito, я написав допис у блозі з докладнішими відомостями про те, як його налаштувати та використовувати: solidsoft.wordpress.com/2018/03/27/…
Marcin Zajączkowski

Чи @Testдостатньо хорошим є метод, котрий коментується, повинен бути загальнодоступним або "приватним пакетом"?
Гік

При проведенні тестів з Юпітером (який часто називають "JUnit 5"), методи тестування мають бути лише видимими в пакеті.
Ніколай

56

Використовуйте 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

    ...
}

5
@ExtendWith(MockitoExtension.class)еквівалентно @RunWith(MockitoJUnitRunner.class)JUnit4
Сергій Немчинов,

9

Існують різні способи, але більш чистий спосіб, який також поважає філософію 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?
haelix

@haelix Оскільки стратегія версій, яка використовується для цієї залежності, покладається на бібліотеку Mockito. Подивіться на версію тут 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.
davidxxx

MockitoExtensionне існує у mockito-coreверсії 3.0.0.
Thunderforge

1
@Thunderforge Це визначено уmockito-junit-jupiter
davidxxx

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