Обзор
Mockito — это мок-фреймворк для модульного тестирования в Java.
Внедрение pom-зависимостей
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>LATEST</version>
</dependency>
Включить Мокито
Создать фиктивный объект через параметр класса (класс, интерфейс), который отличается от реального созданного объекта. Серия статических методов, использующих класс Mockito.
public static <T> T mock(Class <T> classToMock)
Напишите пример Мокито
Mockito должен зависеть от Junit.
package org.byron4j.cookbook.mocketio.basic;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class MockitoAnnotationTest {
@Test
public void whenNotUseMockAnnotation_thenCorrect() {
// 创建一个mock出来的ArrayList对象
List mockList = Mockito.mock(ArrayList.class);
// 调用mock对象的方法
mockList.add("one");
//mockList.add("one");
// 获取mock对象的实际方法,获取size,结果为0
System.out.println("mockList.size(): " + mockList.size());
// toString方法
System.out.println("mockList's toString is: " + mockList);
// 验证mock对象mockList的add方法是否被调用了一次
Mockito.verify(mockList).add("one");
assertEquals(0, mockList.size());
// 当调用mockList.size()的时候,总是返回100
Mockito.when(mockList.size()).thenReturn(100);
assertEquals(100, mockList.size());
}
}
Результат работы:
mockList.size(): 0
mockList's toString is: Mock for ArrayList, hashCode: 409962262
- использовать
List mockList = Mockito.mock(ArrayList.class);
Создайте макет объекта ArrayList mockList - Вызвать метод фиктивного объекта
mockList.add("one");
- тогда позвони
mockList.size()
Результат равен 0, что указывает на то, чтоmockList.add("one");
Код указывает только на то, что произошло само поведение добавления, и не повлияет на другое поведение mockList. - Метод проверки, который проверяет, был ли один раз вызван метод добавления фиктивного объекта mockList.
Mockito.verify(mockList).add("one");
assertEquals(0, mockList.size());
- При вызове mockList.size() он всегда возвращает 100
Mockito.when(mockList.size()).thenReturn(100);
assertEquals(100, mockList.size());
проверить метод
Убедитесь, что включенное поведение (метод) происходит один раз (вызывается один раз), т. е. verify(mock, times(1)), например:verify(mock).someMethod("some arg");
. равноverify(mock, times(1)).someMethod("some arg");
Mockito.verify(mockList).add("one");
равно
Mockito.verify(mockList, Mockito.times(1)).add("one");
Mockito.times(1)
Параметр 1 указывает, что ожидаемое количество выполнений равно 1.
Метод проверки передает два параметра: фиктивный объект, режим проверки.
public static <T> T verify(T mock, VerificationMode mode);
Mockito.times(int WantedNumberOfInvocations) может получить объект VerificationMode, который на самом деле вызывает
VerificationModeFactory.times(wantedNumberOfInvocations)
Получить объект Times:new Times(wantedNumberOfInvocations)
, Times реализует интерфейс VerificationMode.
Параметр 1: фиктивный объект, обязательный
Параметр 2: Режим проверки: times(x), atLeastOnce() или never() и т. д.; если это times(1), этот параметр можно игнорировать.
Стек вызовов метода times выглядит следующим образом:
org.mockito.Mockito#times(int wantedNumberOfInvocations)
org.mockito.internal.verification.VerificationModeFactory#times(int wantedNumberOfInvocations)
org.mockito.internal.verification.Times(int wantedNumberOfInvocations)
когда метод
Метод Mockito.when определяется следующим образом:
public static <T> OngoingStubbing<T> when(T methodCall)
Методу when необходимо передать вызов метода фиктивного объекта.Например, в этом примере мы передаем вызов метода mockList.size() фиктивного объекта mockList.
Метод when оставляет заглушку и вызывается обратно, когда мы хотим, чтобы макет возвращал определенное возвращаемое значение в определенной ситуации.
Простое намерение:当x方法调用的时候,就返回y
.
Пример:
-
when(mock.someMethod()).thenReturn(10);
: возвращает 10 при вызове метода -
when(mock.someMethod(anyString())).thenReturn(10);
: гибкие параметры -
when(mock.someMethod("some arg")).thenThrow(new RuntimeException());
: при вызове метода выбрасывается исключение -
when(mock.someMethod("some arg")).thenThrow(new RuntimeException()).thenReturn("foo");
: последовательные вызовы разного поведения -
when(mock.someMethod("some arg")).thenReturn("one", "two");
: последовательные заглушки, первый вызов возвращает «один», второй и последующие вызовы возвращают «два». -
when(mock.someMethod("some arg")).thenReturn("one").thenReturn("two");
: имеет тот же эффект, что и предыдущий -
when(mock.someMethod("some arg")).thenThrow(new RuntimeException(), new NullPointerException();
: непрерывная заглушка, исключение исключения
@Test
public void whenTest() {
List mock = Mockito.mock(List.class);
Mockito.when(mock.size()).thenReturn(-1);
System.out.println("mock.size():" + mock.size());
// 连续存根
Mockito.when(mock.size()).thenReturn(1).thenReturn(2).thenReturn(3);
for(int i=1; i <= 5; i++){
System.out.println("=====连续存根方式1:=====: " + mock.size());
}
Mockito.when(mock.size()).thenReturn(1,2, 3);
for(int i=1; i <= 5; i++){
System.out.println("#####连续存根方式2:#####: " + mock.size());
}
// 模拟异常
Mockito.when(mock.size()).thenThrow(new RuntimeException(), new NullPointerException());
try{
mock.size();
}catch (Exception e){
System.out.println(e);
}
try{
mock.size();
}catch (Exception e){
System.out.println(e);
}
}
Рабочий вывод:
mock.size():-1
=====连续存根方式1:=====: 1
=====连续存根方式1:=====: 2
=====连续存根方式1:=====: 3
=====连续存根方式1:=====: 3
=====连续存根方式1:=====: 3
#####连续存根方式2:#####: 1
#####连续存根方式2:#####: 2
#####连续存根方式2:#####: 3
#####连续存根方式2:#####: 3
#####连续存根方式2:#####: 3
java.lang.RuntimeException
java.lang.NullPointerException
Включить функцию аннотации Mockito
@RunWith(MockitoJUnitRunner.class) Включить функцию аннотации
использовать@RunWith(MockitoJUnitRunner.class)
Включите функцию аннотации Mockito в классе.
@RunWith(MockitoJUnitRunner.class)
public class MockitoAnnotationStartup {
}
@Мок-аннотация
Мок-объект можно получить с помощью аннотации @Mock, которая эквивалентна Mockito.mock(class).
/**注解得到的mock对象*/
@Mock
List<String> mockList;
等价于
List<String> mock = Mockito.mock(List.class);
Пример выглядит следующим образом:
package org.byron4j.cookbook.mocketio.basic;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class MockitoAnnoTest extends MockitoAnnotationStartup{
/**注解得到的mock对象*/
@Mock
List<String> mockList;
@Test
public void testRaw(){
List<String> mock = Mockito.mock(List.class);
mock.add("one");
mock.add("one");
Mockito.verify(mock, Mockito.times(2)).add("one");
Mockito.when(mock.size()).thenReturn(100);
assertEquals(100, mock.size());
}
@Test
public void testAnno(){
mockList.add("one");
mockList.add("one");
Mockito.verify(mockList, Mockito.times(2)).add("one");
Mockito.when(mockList.size()).thenReturn(100);
assertEquals(100, mockList.size());
}
}
@Шпионская аннотация
Подобно аннотации @Mock, существует также аннотация @Spy. шпион - это значение шпиона, шпиона, подделки.
List<String> mock = Mockito.spy(List.class);
использовать аннотации
@Spy
List<String> spyList;
Аннотация @Captor (захват параметров)
Захватчик параметров ArgumentCaptor соответствует аннотации @Captor.
Оригинальный способ создания перехватчика параметров:
@Test
public void whenNotUseCaptorAnnotation_thenCorrect() {
List mockList = Mockito.mock(List.class);
ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.class);
mockList.add("one");
Mockito.verify(mockList).add(arg.capture());
assertEquals("one", arg.getValue());
}
Создайте захват параметров с аннотацией @Captor:
@Mock
List mockedList;
@Captor
ArgumentCaptor argCaptor;
@Test
public void whenUseCaptorAnnotation_thenTheSam() {
mockedList.add("one");
Mockito.verify(mockedList).add(argCaptor.capture());
assertEquals("one", argCaptor.getValue());
}
-
ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.class);
: создать перехватчик параметров -
Mockito.verify(mockedList).add(argCaptor.capture());
: Используйте метод захвата в проверке для захвата параметров добавления метода; метод захвата должен быть в проверке. -
argCaptor.getValue()
: получить параметры, захваченные устройством захвата параметров.
@InjectMocks аннотация
@InjectMocks
Аннотации могут автоматически внедрять фиктивные свойства в тестовый объект.
@Mock
Map<String, String> wordMap;
@InjectMocks
MyDictionary myDictionary = new MyDictionary();
@Test
public void testInjectMocks(){
Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning");
assertEquals("aMeaning", myDictionary.getMeaning("aWord"));
System.out.println(myDictionary.getMeaning("aWord"));
}
class MyDictionary{
Map<String, String> wordMap;
public String getMeaning(String word){
return wordMap.get(word);
}
}
- Класс MyDictionary имеет свойство wordMap:
Map<String, String> wordMap;
- Смоделируйте переменную с именем wordMap :
@Mock
Map<String, String> wordMap;
- Отметьте его аннотацией @InjectMocks:
@InjectMocks
MyDictionary myDictionary = new MyDictionary();
Поддельный объект wordMap будет внедрен в одноименное свойство экземпляра myDictionary.
Меры предосторожности:
Используйте аннотации, чтобы свести к минимуму дублирование кода для создания фиктивных объектов.
Используйте аннотации, чтобы сделать тестовые случаи более читабельными
Вставка объектов @Spy и @Mock с помощью аннотации @InjectMocks
Использованная литература:
- Официальный сайт Мокито:static.Java doc.IO/org.mock ITO…