Академический Документы
Профессиональный Документы
Культура Документы
на языке Java
Урок 13
Использование
JUnit и Mockito
Содержание
1. Модульное тестирование.................................................... 4
2. JUnit...................................................................................... 11
2.1. Назначение JUnit..............................................................11
2.2. Создание тестирующего класса в Eclipse...................12
2.3. Структура фреймворка JUnit........................................16
2.4. Простой тест на положительный сценарий..............18
2.5. Фикстуры...........................................................................20
2.6. Тестирование исключительных ситуаций.................24
2.7. Тестирование времени выполнения метода..............27
2.8. Игнорирование тестов....................................................28
2.9. Правила (Rules).................................................................28
2.10. Наборы тестов.................................................................32
2.11. Параметризованные тесты..........................................34
2.12. JUnit 5................................................................................38
3. Mockito.................................................................................. 40
3.1. Назначение фреймворка Mockito.................................40
3.2. Настройка Eclipse для работы с Mockito....................41
2
Содержание
3
Использование JUnit и Mockito
1. Модульное тестирование
Под тестированием кода понимается проверка соот-
ветствия между ожидаемым и реальным поведением про-
граммной системы. Тестирование может выполняться как
самими программистами-разработчиками, так и специ-
ально обученными специалистами (тестировщиками).
В зависимости от анализируемых аспектов кода раз-
личают следующие виды тестирования:
1. Функциональное тестирование — проверка того,
что код адекватно выполняет свою задачу и соот-
ветствует спецификации на него. Проверяется пра-
вильность работы всех методов кода: возвращаемые
значения, выбрасываемые исключения и изменения
в состоянии системы после выполнения каждого ме-
тода.
2. Тестирование производительности — оценка того,
насколько быстро работает программа в обычных
и в стрессовых условиях (например, при большом
количестве пользователей интернет-магазин не дол-
жен замедлять свою работу или вообще становиться
недоступным).
3. Тестирование удобства использования — обычно
выполняется вручную специальным тестировщи-
ком-юзабилистом. Такой тестировщик кликает по
кнопкам, переходит по ссылкам и т.п., чтобы прове-
рить работу интерфейса программы.
4. Тестирование безопасности — проверка того, что
код не дает потенциальной возможности доступа
4
Модульное тестирование
5
Использование JUnit и Mockito
6
Модульное тестирование
7
Использование JUnit и Mockito
8
Модульное тестирование
9
Использование JUnit и Mockito
10
JUnit
2. JUnit
2.1. Назначение JUnit
JUnit — это один из наиболее популярных фреймвор
ков для разработки юнит-тестов (модульного тестирова-
ния) на Java. Он был создан Кентом Беком и Эриком Гаммой
(первая версия фреймворка для языка Smalltalk появилась
в 1999 г). Аналогичные оболочки для модульного тестиро-
вания существуют и для других языков программирования.
Они носят общее название — семейство XUnit.
Сегодня наиболее популярна версия JUnit 4. Пре
дыдущая версия JUnit 3 предполагала жесткие правила
задания имен тестирующих классов и методов, а также
наследование от суперкласса TestCase. Вместо этого чет-
вертая версия предполагает использовать аннотации.
Осенью 2017 года была анонсирована версия JUnit 5
(JUnit Jupiter), в которой изменились имена некоторых
аннотаций и были добавлены ряд упрощений и допол
нительных удобств.
Большинство современных IDE при создании тесто-
вого класса предлагает выбрать версию JUnit, с которой
привык работать программист. В этом разделе все при-
меры ориентированы на JUnit 4, а в конце дается краткий
обзор возможностей и отличий JUnit 5.
Как правило, модульные тесты разрабатываются с ис-
пользованием IDE параллельно с разработкой кода. За-
тем они интегрируются в какую-либо систему управления
версиями (ANT, Maven и т.п.) и запускаются регулярно
в автоматическом режиме. Но иногда политика компании-
11
Использование JUnit и Mockito
package mycalc;
public class Calculator {
public double add(double a, double b) {
return a+b;
}
public double sub(double a, double b) {
return a-b;
}
public double mult(double a, double b) {
return a*b;
}
public double div(double a, double b) {
return a/b;
}
}
12
JUnit
13
Использование JUnit и Mockito
14
JUnit
15
Использование JUnit и Mockito
Аннотация Описание
@Test Определяет, что следующий за аннотацией метод
является тестовым
@Before Указывает, что следующий за аннотацией метод
будет выполняться перед каждым тестом
@After Указывает, что следующий за аннотацией метод
будет выполняться после каждого теста
@BeforeClass Указывает, что следующий за аннотацией метод
будет выполнен перед всеми тестами в момент их
запуска
@AfterClass Указывает, что следующий за аннотацией метод
будет выполнен после всех тестов
@Ignore Указывает, что следующий метод будет пропущен
(проигнорирован) в момент тестирования
16
JUnit
Аннотация Описание
fail ([String message]) Проваливает тест, выдавая тексто-
вое сообщение (или без него)
assertTrue([String message,] Проверяет, что логическое условие
boolean condition) истинно
assertFalse([String message,] Проверяет, что логическое условие
boolean condition) ложно
assertEquals([String message], Проверяет, что два значения
Object expected, Object actual) объектов совпадают. Для при-
митивных типов проверяется
обычное равенство, для объектов
сравнивается содержимое методом
equals(). Исключение — массивы
(для них сравниваются ссылки, а не
содержимое)
assertEquals([String message], Проверяет, что два вещественных
double expected, double actual, числа совпадают с заданной точ-
double delta) ностью
assertNull([String message], Проверяет, что объектная ссылка
Object object) является пустой (null)
assertNotNull([String message], Проверяет, что объектная ссылка не
Object object) является пустой
assertSame(([String message], Проверяет, что обе ссылочные пере
Object expected, Object actual) менные относятся к одному объекту
assertNotSame(([String Проверяет, что обе ссылочные
message], Object expected, переменные не относятся к одному
Object actual) объекту
17
Использование JUnit и Mockito
18
JUnit
@Test
public void testAdd() {
Calculator calc=new Calculator(); //arrange:
// создание объекта
int result=calc.add(8,2); // act: выполнение метода
assertEquals(10, result); // assert: проверка
}
@Test
public void testAdd() {
Calculator calc=new Calculator(); // arrange:
// создание объекта
19
Использование JUnit и Mockito
20
JUnit
package mycalc;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
21
Использование JUnit и Mockito
@After
public void tearDown() {
calc=null; // удаление объекта после теста
}
@Test
public void testAdd() {
double result=calc.add(8,2); // act: выполнение
// метода
assertEquals(10, result,1e-9); // assert: проверка
}
@Test
public void testSub() {
double result=calc.sub(8,2);
assertEquals(6, result,1e-9);
}
// Остальные тесты
}
package mycalc;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;
22
JUnit
@BeforeClass
public static void setUp() {
calc=new Calculator(); // arrange: создание
// объекта
}
@Test
public void testAdd() {
double result=calc.add(8,2); // act: выполнение
// метода
assertEquals(10, result,1e-9); // assert:
// проверка
}
@Test
public void testSub() {
double result=calc.sub(8,2);
assertEquals(6, result,1e-9);
}
// остальные тесты
}
23
Использование JUnit и Mockito
package mycalc;
24
JUnit
@Test
public void testDiv() throws DivByZeroException{
double result=calc.div(8,2);
assertEquals(4, result,1e-9);
}
25
Использование JUnit и Mockito
@Test
public void testDivByZeroMessage() {
try {
double result=calc.div(8,0);
fail(“Division by Zero should have thrown
a DivByZeroException”);
}
catch(DivByZeroException e){
assertEquals(“Division by Zero”,
e.getMessage());
}
catch(Exception e) {
fail(“Should be DivByZeroException,
but have “ + e.getClass());
}
}
26
JUnit
@Test(timeout=10)
public void testTimeOut() throws InterruptedException{
for(long i=1;i<10;i++) {
double result=calc.mult(i, i+1);
double expected=i*(i+1);
assertEquals(expected,result,1e-9);
Thread.sleep(2);
}
}
27
Использование JUnit и Mockito
28
JUnit
29
Использование JUnit и Mockito
result=Double.parseDouble(numbers[i]); //
// преобразование в число
assertEquals(3*(i+2),result,1e-9);// проверка
}
}
@Rule
public final ExpectedException exception =
ExpectedException.none(); // пустое
// исключение
… // другие тесты без генерации исключений
30
JUnit
@Rule
public final Timeout globalTimeOut=Timeout.millis(200);
@Test
public void testTimeOut() throws InterruptedException{
for(long i=1;i<10;i++) {
31
Использование JUnit и Mockito
32
JUnit
33
Использование JUnit и Mockito
package mycalc;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({ CalculatorTest.class,
StringAnaliserTest.class })
public class AllTests {
}
@RunWith(Parameterized.class)
public class CalculatorTest {
…//код тестирующего класса
}
34
JUnit
@RunWith(Parameterized.class)
public class CalculatorTest {
private double num1;
private double num2;
private double expectedResult;
private static Calculator calc;
public CalculatorTest(double num1, double num2,
double expectedResult) {
this.num1 = num1;
this.num2 = num2;
this.expectedResult=expectedResult;
}
…
}
@Parameters(name=”{index}:mult({0},{1})= {2}”)
public static Collection<Object[]> dataForTests(){
return Arrays.asList(new Object[][] {
{2,3,6},{2,7,14},{0,3,0}});
}
35
Использование JUnit и Mockito
@Test
public void testMult() {
double result=calc.mult(num1,num2);
assertEquals(expectedResult, result,1e-9);
}
36
JUnit
package mycalc;
import static org.junit.Assert.*;
@RunWith(Parameterized.class)
public class CalculatorTest {
private double num1;
private double num2;
private double expectedResult;
private static Calculator calc;
@BeforeClass
public static void setUp() {
calc=new Calculator();
}
@Test
public void testMult() {
double result=calc.mult(num1,num2);
assertEquals(expectedResult, result,1e-9);
}
37
Использование JUnit и Mockito
JUnit 4 JUnit 5
@BeforeClass @BeforeAll
@Before @BeforeEach
@AfterClass @AfterAll
@After @AfterEach
@Ignore @Disabled
38
JUnit
39
Использование JUnit и Mockito
3. Mockito
3.1. Назначение фреймворка Mockito
Модульное тестирование предполагает изоляцию
исследуемого класса от его окружения. Но на деле реа-
лизовать эту изоляцию непросто. Например, для работы
тестируемого класса нужны данные, которые ему предо-
ставляет другой класс (берет их из базы данных или от
внешнего Web-сервиса).
Во время тестирования нужно как-то «подменить»
работу этого внешнего класса некоторой простой «за-
глушкой». Это даст уверенность в том, что окружение ра-
ботает корректно и предсказуемо, и что обнаруживаемые
ошибки сосредоточены именно в тестируемом модуле.
Кроме того, во время тестирования одного модуля взаи-
модействующие с ним классы могут быть еще не созданы
или не до конца отлажены.
Принято выделять два основных вида «заглушек»
(или тестовых дублеров): стабы (stub) и моки (mock). Для
создания стабов не обязательно использовать дополни-
тельные фреймворки, их можно реализовать средствами
Java Core. При этом работа программиста будет достаточ-
на сложна, а полученный результат имеет ограниченные
возможности применения.
Для создания моков на Java можно использовать фрей-
мворк Mockito. С его помощью легко и динамично созда-
ются объекты, имитирующие окружение тестируемого
модуля. Функциональность таких объектов значительно
выше, чем у стабов, а работы программисту — меньше.
40
Mockito
41
Использование JUnit и Mockito
42
Mockito
43
Использование JUnit и Mockito
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
</dependencies>
44
Mockito
45
Использование JUnit и Mockito
46
Mockito
for(String todo:todos) {
if(todo.contains(“Spring”)) {
filteredTodos.add(todo);
}
}
return filteredTodos;
}
}
47
Использование JUnit и Mockito
48
Mockito
@Override
public List<String> retrieveTodos(String user) {
return Arrays.asList(“Learn Spring MVC”,”Learn
Spring”,”Learn to Dance”);
}
}
49
Использование JUnit и Mockito
50
Mockito
TodoBusinessImpl todoBusinessImpl =
new TodoBusinessImpl(todoServiceMock);
when(todoServiceMock.retrieveTodos(“Dummy”)).
thenReturn(todos);
@Test
public void testWithMock() {
// создание мока
TodoService todoServiceMock =
mock(TodoService.class);
51
Использование JUnit и Mockito
@Test
public void listTest() {
// создание мока,подменяющего List
List listMock = mock(List.class);
52
Mockito
@Test
public void listTestMultiple() {
// создание мока,подменяющего List
List listMock = mock(List.class);
// настройка: при вызове метода size()
// первый раз должно возвращаться 2
// а второй и последующие разы 3
when(listMock.size()).thenReturn(2).thenReturn(3);
// вызов size() и проверки
assertEquals(2,listMock.size());
assertEquals(3,listMock.size());
assertEquals(3,listMock.size());
}
53
Использование JUnit и Mockito
@Test
public void listTestGet() {
// создание мока,подменяющего List
List listMock = mock(List.class);
// настройка: при вызове метода get(0)
// должна возвращаться строка “result”
when(listMock.get(0)).thenReturn(“result”);
// вызов get() и проверка, что результат “result”
assertEquals(“result”,listMock.get(0));
assertEquals(null,listMock.get(1)); // по умолчанию
// результат null
}
@Test
public void listTestGetAnyParametr() {
// создание мока,подменяющего List
List listMock=mock(List.class);
// настройка: при вызове метода get() c любым целым
// параметром должна возвращаться строка “result”
when(listMock.get(anyInt())).thenReturn(“result”);
54
Mockito
55
Использование JUnit и Mockito
56
Mockito
57
Использование JUnit и Mockito
58
Mockito
59
Использование JUnit и Mockito
60
Mockito
verify(todoServiceMock,times(2)).
deleteTodo(stringArgCaptor.capture());
// проверка количества захваченных аргументов
assertThat(stringArgCaptor.getAllValues().
size(),is(2));
}
61
Использование JUnit и Mockito
62
Mockito
63
Урок 13.
Использование JUnit и Mockito