Mockito模拟示例
时间:2020-02-23 14:40:44 来源:igfitidea点击:
Mockito模拟框架提供了模拟类的不同方法。
让我们看一下可以模拟类并显示其行为的不同方法。
Mockito模拟方法
我们可以使用Mockito类的mock()方法创建给定类或者接口的模拟对象。
这是模拟对象的最简单方法。
package com.theitroad.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<String> mockList = mock(List.class);
when(mockList.size()).thenReturn(5);
assertTrue(mockList.size()==5);
}
}
我们使用JUnit 5与Mockito一起编写测试用例来模拟对象。
Mockito @模拟注解
我们也可以使用@Mock注释来模拟对象。
当我们想在多个地方使用模拟对象时,这很有用,因为我们避免了多次调用mock()方法。
代码变得更具可读性,我们可以指定模拟对象名称,以防出现错误。
使用@Mock注释时,必须确保调用MockitoAnnotations.initMocks(this)来初始化模拟对象。
我们可以在测试之前执行的测试框架设置方法中执行此操作。
package com.theitroad.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<String> 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("theitroad");
assertEquals("theitroad", mockList.get(0));
}
}
Mockito @InjectMocks批注
当我们要将一个模拟对象注入另一个模拟对象时,可以使用@InjectMocks批注。
@InjectMock创建类的模拟对象,并将带有注释@Mock的模拟注入到该类中。
package com.theitroad.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<String> 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<String> names;
public List<String> getNames() {
return names;
}
public void setNames(List<String> names) {
this.names = names;
}
}
Mockito spy()进行部分模拟
如果我们只想模拟特定的行为,并调用未受干扰行为的真实方法,则可以使用Mockito spy()方法创建一个间谍对象。
package com.theitroad.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<String> list = new ArrayList<>();
List<String> spyOnList = spy(list);
when(spyOnList.size()).thenReturn(10);
assertEquals(10, spyOnList.size());
//calling real methods since below methods are not stubbed
spyOnList.add("hyman");
spyOnList.add("Meghna");
assertEquals("hyman", spyOnList.get(0));
assertEquals("Meghna", spyOnList.get(1));
}
}
Mockito @Spy注释
我们可以使用@Spy注释监视对象。
让我们看一个简单的例子。
package com.theitroad.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批注会尝试调用no-args构造函数以初始化模拟对象。
如果您的程序没有该程序,则会收到以下错误。
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.theitroad.mockito.mock.MockitoSpyAnnotationExample.setup(MockitoSpyAnnotationExample.java:18)
另外,请注意,Mockito无法实例化内部类,局部类,抽象类和接口。
因此,最好提供一个实例进行监视。
否则,实际的方法可能不会被调用并被静默忽略。
例如,如果您指定一个间谍对象,如下所示:
@Spy List<String> spyList;
您会注意到,当您调用add()或者get()方法时,不会调用实际方法。
如果您指定如下所示的间谍对象,那么一切都会正常进行。
@Spy List<String> spyList = new ArrayList<>();

