Автор оригинала: Pankaj Kumar.
Платформа издевательств Mockito предоставляет различные способы издевательства над классом. Давайте рассмотрим различные методы, с помощью которых мы можем издеваться над классом и заглушать его поведение.
Имитационный метод Mockito
Мы можем использовать метод Mockito class mock() для создания макетного объекта данного класса или интерфейса. Это самый простой способ издеваться над объектом.
package com.journaldev.mockito.mock; import java.util.List; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; public class MockitoMockMethodExample { @SuppressWarnings("unchecked") @Test public void test() { // using Mockito.mock() method ListmockList = mock(List.class); when(mockList.size()).thenReturn(5); assertTrue(mockList.size()==5); } }
Мы используем JUnit 5 для написания тестовых примеров в сочетании с Mockito для моделирования объектов.
Mockito @Макет Аннотации
Мы также можем издеваться над объектом, используя аннотацию @Mock. Это полезно, когда мы хотим использовать издевательский объект в нескольких местах, потому что мы избегаем многократного вызова метода mock (). Код становится более читабельным, и мы можем указать имя макетного объекта, которое будет полезно в случае ошибок.
При использовании аннотации @Mock мы должны убедиться, что вызываем MockitoAnnotations.initMocks(это)
для инициализации объекта, над которым издеваются. Мы можем сделать это в методах настройки платформы тестирования, которые выполняются перед тестами.
package com.journaldev.mockito.mock; import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class MockitoMockAnnotationExample { @Mock ListmockList; @BeforeEach public void setup() { //if we don't call below, we will get NullPointerException MockitoAnnotations.initMocks(this); } @SuppressWarnings("unchecked") @Test public void test() { when(mockList.get(0)).thenReturn("JournalDev"); assertEquals("JournalDev", mockList.get(0)); } }
Аннотация Mockito @InjectMocks
Когда мы хотим внедрить издевательский объект в другой издевательский объект, мы можем использовать аннотацию @InjectMocks. @@Injectmocks создает макет объекта класса и вводит в него насмешки, отмеченные аннотациями @Mock.
package com.journaldev.mockito.mock; import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class MockitoInjectMockAnnotationExample { @Mock ListmockList; //@InjectMock creates an instance of the class and //injects the mocks that are marked with the annotations @Mock into it. @InjectMocks Fruits mockFruits; @BeforeEach public void setup() { //if we don't call below, we will get NullPointerException MockitoAnnotations.initMocks(this); } @SuppressWarnings("unchecked") @Test public void test() { when(mockList.get(0)).thenReturn("Apple"); when(mockList.size()).thenReturn(1); assertEquals("Apple", mockList.get(0)); assertEquals(1, mockList.size()); //mockFruits names is using mockList, below asserts confirm it assertEquals("Apple", mockFruits.getNames().get(0)); assertEquals(1, mockFruits.getNames().size()); mockList.add(1, "Mango"); //below will print null because mockList.get(1) is not stubbed System.out.println(mockList.get(1)); } } class Fruits{ private List names; public List getNames() { return names; } public void setNames(List names) { this.names = names; } }
Mockito spy() для частичного издевательства
Если мы хотим имитировать только определенное поведение и вызывать реальные методы для ненаблюдаемого поведения, мы можем создать объект-шпион, используя метод Mockito spy ().
package com.journaldev.mockito.mock; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Test; public class MockitoSpyMethodExample { @Test public void test() { Listlist = new ArrayList<>(); List spyOnList = spy(list); when(spyOnList.size()).thenReturn(10); assertEquals(10, spyOnList.size()); //calling real methods since below methods are not stubbed spyOnList.add("Pankaj"); spyOnList.add("Meghna"); assertEquals("Pankaj", spyOnList.get(0)); assertEquals("Meghna", spyOnList.get(1)); } }
Mockito @Шпионская аннотация
Мы можем использовать аннотацию @Spy для слежки за объектом. Давайте рассмотрим простой пример.
package com.journaldev.mockito.mock; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.MockitoAnnotations; import org.mockito.Spy; public class MockitoSpyAnnotationExample { @Spy Utils mockUtils; @BeforeEach public void setup() { MockitoAnnotations.initMocks(this); } @Test public void test() { when(mockUtils.process(1, 1)).thenReturn(5); //mocked method assertEquals(5, mockUtils.process(1, 1)); //real method called since it's not stubbed assertEquals(20, mockUtils.process(19, 1)); } } class Utils{ public int process(int x, int y) { System.out.println("Input Params = "+x+","+y); return x+y; } }
Обратите внимание, что аннотация @Spy пытается вызвать конструктор без аргументов для инициализации издевательского объекта. Если в вашем классе его нет, вы получите следующую ошибку.
org.mockito.exceptions.base.MockitoException: Unable to initialize @Spy annotated field 'mockUtils'. Please ensure that the type 'Utils' has a no-arg constructor. at com.journaldev.mockito.mock.MockitoSpyAnnotationExample.setup(MockitoSpyAnnotationExample.java:18)
Кроме того, обратите внимание, что Mockito не может создавать экземпляры внутренних классов, локальных классов, абстрактных классов и интерфейсов. Поэтому всегда полезно предоставить экземпляр для слежки. В противном случае реальные методы могут не вызываться и молча игнорироваться.
Например, если вы укажете объект-шпион, как показано ниже:
@Spy ListspyList;
Вы заметите, что при вызове add()
или get()
методов реальные методы не вызываются. Если вы укажете объект-шпион, как показано ниже, то все будет работать нормально.
@Spy ListspyList = new ArrayList<>();
Резюме
Mockito mocking framework позволяет нам легко создавать макет объекта с помощью различных методов и аннотаций. Мы также можем внедрить макет объекта в другой макет объекта, это очень полезная функция.