Статьи

Сотрудничество Юнит и Мокито

На этот раз я хочу сделать обзор инфраструктуры тестирования Mockito. Определенно это один из самых популярных инструментов для тестирования кода Java. Я уже сделал обзор конкурента MockitoEasyMock . Этот пост будет основан на примере приложения из поста о EasyMock. Я имею в виду классы, которые представляют функциональность кофемашины.

Подготовка тестирования с Mockito

Как обычно, я буду использовать Maven для настройки проекта. Поэтому, чтобы сделать Mockito доступным в проекте, мне нужно добавить следующую зависимость в файл pom.xml:

01
02
03
04
05
06
07
08
09
10
11
12
<dependencies>
    <dependency>
        <groupid>org.mockito</groupid>
        <artifactid>mockito-all</artifactid>
        <version>1.9.5</version>
    </dependency>
    <dependency>
        <groupid>junit</groupid>
        <artifactid>junit</artifactid>
        <version>4.11</version>
    </dependency>
</dependencies>

Обратите внимание, что JUnit не требуется для нормальной функциональности Mockito, вы можете использовать вместо него TestNG. Таким образом, вы можете использовать JUnit или TestNG в зависимости от вашего решения.

Давайте двигаться дальше. Как я упоминал ранее, все тесты в этой статье будут написаны для примера приложения из поста о EasyMock . Оттуда вы можете прочитать только раздел «Код приложения». Этого будет достаточно, чтобы понять предмет тестирования.

Mockito & JUnit тесты

Я хочу начать этот раздел с нескольких предложений о фреймворке Mockito . Определенно с помощью Mockito вы можете делать все, что пожелаете в тестировании. Вы можете создавать макеты, заглушки, проверять и все это с помощью понятного API.
Пришло время посмотреть, как выглядят юнит-тесты с Mockito.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
 
import com.app.data.Portion;
import com.app.exceptions.NotEnoughException;
import com.app.mechanism.CoffeeMachine;
import com.app.mechanism.interfaces.ICoffeeMachine;
import com.app.mechanism.interfaces.IContainer;
 
@RunWith(MockitoJUnitRunner.class)
public class CoffeeMachineTest {
 
    ICoffeeMachine coffeeMachine;
 
    @Mock
    IContainer coffeeContainer;
    @Mock
    IContainer waterContainer;
 
    @Before
    public void setUp() {
        coffeeMachine = new CoffeeMachine(coffeeContainer, waterContainer);
    }
 
    @After
    public void tearDown() {
        coffeeContainer = null;
        waterContainer = null;
        coffeeMachine = null;      
    }
 
    @Test
    public void testMakeCoffe() throws NotEnoughException {
 
        when(coffeeContainer.getPortion(Portion.LARGE)).thenReturn(true);
        when(waterContainer.getPortion(Portion.LARGE)).thenReturn(true);
 
        assertTrue(coffeeMachine.makeCoffee(Portion.LARGE));
    }
 
    @Test
    public void testNotEnoughException() throws NotEnoughException {
 
        when(coffeeContainer.getPortion(Portion.SMALL)).thenReturn(false);
        when(waterContainer.getPortion(Portion.SMALL)).thenReturn(true);
 
        assertFalse(coffeeMachine.makeCoffee(Portion.SMALL));
 
    }
 
}

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

1
2
3
4
5
6
...
    @Mock
    IContainer coffeeContainer;
    @Mock
    IContainer waterContainer;
...

В коде выше я объявил две насмешки. Создание макетов таким способом требует аннотации @RunWith (MockitoJUnitRunner.class), применяемой к тестовому классу. В качестве альтернативы вы можете использовать MockitoAnnotations.initMocks (testClass); перед выполнением любого теста, например, вы можете поместить этот фрагмент кода в метод, помеченный @Before .

1
2
3
...
when(coffeeContainer.getPortion(Portion.LARGE)).thenReturn(true);
...

Определение поведения макета в Mockito выполняется очень удобным способом. Вы указываете, что должно быть возвращено после вызова конкретного метода. Обратите внимание, что я сделал несколько статических импортов в тестовом классе.

Резюме

Рамки Mockito покорили мое сердце. Это очень удобно, его API понятен, использование лаконично. Mockito содержит множество методов, которые могут понадобиться при разработке модульных тестов. Конечно, один пост слишком мал, чтобы описать все возможности Mockito, поэтому я рекомендую вам углубиться, перейдя по ссылке на официальную документацию .

Справка: сотрудничество JUnit и Mockito от нашего партнера по JCG Алексея Зволинского в блоге Фрузенштейна .