Рубрики
Без рубрики

Издевательские примеры

Пример макета Mockito, аннотация Mockito @Mock, пример Mockito @InjectMocks, пример Mockito @Spy, метод шпиона Mockito, макет инъекции Mockito, частичный макет.

Автор оригинала: 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
		List mockList = 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
	List mockList;
	
	@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
	List mockList;
	
	//@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() {
		List list = 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
List spyList;

Вы заметите, что при вызове add() или get() методов реальные методы не вызываются. Если вы укажете объект-шпион, как показано ниже, то все будет работать нормально.

@Spy
List spyList = new ArrayList<>();

Резюме

Mockito mocking framework позволяет нам легко создавать макет объекта с помощью различных методов и аннотаций. Мы также можем внедрить макет объекта в другой макет объекта, это очень полезная функция.