Mockito 是一个模拟测试框架,主要功能是在单元测试中模拟类/对象的行为。
单元测试 – Mockito入门
1、mock()方法
org.mockito.Mockito 的 mock 方法可以模拟类和接口,以下代码演示直接在Test方法中对类和接口进行Mock
@Test
public void test() {
List mockList = mock(List.class);
// mock对象的方法返回值默认都是返回类型的默认值。例如返回类型是int,默认返回值是0;类型是一个类,默认返回值是null。
Assert.assertEquals(0, mockList.size());
Assert.assertEquals(null, mockList.get(0));
// 调用 mock 对象的写方法,是没有效果的
mockList.add("a");
// 没有指定 size() 方法返回值,这里结果是默认值
Assert.assertEquals(0, mockList.size());
// 没有指定 get(0) 返回值,这里结果是默认值
Assert.assertEquals(null, mockList.get(0));
// 指定 get(0)时返回 a
when(mockList.get(0)).thenReturn("a");
// 没有指定 size() 方法返回值,这里结果是默认值
Assert.assertEquals(0, mockList.size());
// 因为上面指定了 get(0) 返回 a,所以这里会返回 a
Assert.assertEquals("a", mockList.get(0));
// 没有指定 get(1) 返回值,这里结果是默认值
Assert.assertEquals(null, mockList.get(1));
// 指定 size()返回123
when(mockList.size()).thenReturn(123);
Assert.assertEquals(123, mockList.size());
}
2、@Mock 注解
@Mock 注解可以理解为对 mock 方法的一个替代。使用该注解时,要使用MockitoAnnotations.openMocks
方法,让注解生效。所以相对于1中的单测,会变成如下的形式。
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.List;
import static org.mockito.Mockito.when;
public class Mocktio {
@Mock
private List mockList;
@Before
public void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
public void test() {
// mock 对象的方法的返回值默认都是返回类型的默认值。例如返回类型是一个类,默认返回值是 null。
Assert.assertEquals(0, mockList.size());
Assert.assertEquals(null, mockList.get(0));
// 调用 mock 对象的写方法,是没有效果的
mockList.add("a");
// 没有指定 size() 方法返回值,这里结果是默认值
Assert.assertEquals(0, mockList.size());
// 没有指定 get(0) 返回值,这里结果是默认值
Assert.assertEquals(null, mockList.get(0));
// 指定 get(0)时返回 a
when(mockList.get(0)).thenReturn("a");
// 没有指定 size() 方法返回值,这里结果是默认值
Assert.assertEquals(0, mockList.size());
// 因为上面指定了 get(0) 返回 a,所以这里会返回 a
Assert.assertEquals("a", mockList.get(0));
// 没有指定 get(1) 返回值,这里结果是默认值
Assert.assertEquals(null, mockList.get(1));
// 指定 size()返回123
when(mockList.size()).thenReturn(123);
Assert.assertEquals(123, mockList.size());
}
}
3、MockitoJUnitRunner
MockitoAnnotations.initMocks 的一个替代方案是使用 MockitoJUnitRunner ,具体的代码变形为
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.List;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class Mocktio {
@Mock
private List mockList;
@Test
public void test() {
// mock 对象的方法的返回值默认都是返回类型的默认值。例如返回类型是一个类,默认返回值是 null。
Assert.assertEquals(0, mockList.size());
Assert.assertEquals(null, mockList.get(0));
// 调用 mock 对象的写方法,是没有效果的
mockList.add("a");
// 没有指定 size() 方法返回值,这里结果是默认值
Assert.assertEquals(0, mockList.size());
// 没有指定 get(0) 返回值,这里结果是默认值
Assert.assertEquals(null, mockList.get(0));
// 指定 get(0)时返回 a
when(mockList.get(0)).thenReturn("a");
// 没有指定 size() 方法返回值,这里结果是默认值
Assert.assertEquals(0, mockList.size());
// 因为上面指定了 get(0) 返回 a,所以这里会返回 a
Assert.assertEquals("a", mockList.get(0));
// 没有指定 get(1) 返回值,这里结果是默认值
Assert.assertEquals(null, mockList.get(1));
// 指定 size()返回123
when(mockList.size()).thenReturn(123);
Assert.assertEquals(123, mockList.size());
}
}
4、参数匹配
// 可以使用 Mockito.anyInt() 匹配所有类型为 int 的参数
when(mockList.get(anyInt())).thenReturn("a");
Assert.assertEquals("a", mockList.get(0));
Assert.assertEquals("a", mockList.get(1));
mockito 有多种匹配函数,部分如下:
函数名 | 匹配类型 |
---|---|
any() | 所有对象类型 |
anyInt() | 基本类型 int、非 null 的 Integer 类型 |
anyChar() | 基本类型 char、非 null 的 Character 类型 |
anyShort() | 基本类型 short、非 null 的 Short 类型 |
anyBoolean() | 基本类型 boolean、非 null 的 Boolean 类型 |
anyDouble() | 基本类型 double、非 null 的 Double 类型 |
anyFloat() | 基本类型 float、非 null 的 Float 类型 |
anyLong() | 基本类型 long、非 null 的 Long 类型 |
anyByte() | 基本类型 byte、非 null 的 Byte 类型 |
anyString() | String 类型(不能是 null) |
anyList() | List<T> 类型(不能是 null) |
anyMap() | Map<K, V> 类型(不能是 null) |
anyCollection() | Collection<T> 类型(不能是 null) |
anySet() | Set<T> 类型(不能是 null) |
any(Class<T> type) |
type类型的对象(不能是 null) |
isNull() | null |
notNull() | 非 null |
5、@Spy 注解
spy 和 mock不同,不同点是:
- spy 的参数是对象示例,mock 的参数是 class。
- 被 spy修饰的对象,调用其方法时默认会走真实方法。mock 对象不会。
@RunWith(MockitoJUnitRunner.class)
public class Mocktio {
@Mock
private ExampleService spyExampleService;
@Test
public void test_spy() {
//Assert.assertEquals(3, spyExampleService.add(1, 2));
when(spyExampleService.add(1, 2)).thenReturn(10);
Assert.assertEquals(10, spyExampleService.add(1, 2));
}
class ExampleService {
int add(int a, int b) {
System.out.println("方法调用被执行");
return a+b;
}
}
}
// Console打印为空
//如果我们将@Mock注解替换为@Spy 去除单行注释//Assert.assertEquals(3, spyExampleService.add(1, 2)); COnsole打印:
方法调用被执行
方法调用被执行