Mockito是一个流行的Mocking框架。它使用起来简单,学习成本非常低。并且具有非常简洁的API,測试代码的可读性非常高。因此它十分受欢迎,用 户群越来越多。非常多的开源的软件也选择了Mockito。

要想了解很多其它有关Mockito的信息。请訪问它的官方网 站:http://mockito.org/

一、简单演示样例

/*
* Creation : 2015年8月14日
*/
package com.tan.test; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import java.util.Iterator;
import java.util.List;
import java.util.Map; import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer; import edu.emory.mathcs.backport.java.util.LinkedList; public class MockitoTest {
/**
* 通过when(mock.someMethod()).thenReturn(value) 来设定mock对象某个方法调用时的返回值
*/
@Test
public void simpleTest() {
// arrange
Iterator i = mock(Iterator.class);
when(i.next()).thenReturn("Hello").thenReturn("World");
// act
String result = i.next() + " " + i.next();
// 验证i.next()是否被调用了2次。不关心返回值
verify(i, times(2)).next();
// 断言结果是否和预期一样
assertEquals("Hello World", result);
} /**
* 參数匹配器--Argument matchers test.
*/
@Test
public void argumentMatchersTest() {
List<String> mock = mock(List.class);
// anyInt()參数匹配器来匹配不论什么的int 类型的參数
when(mock.get(anyInt())).thenReturn("Hello").thenReturn("World"); // 所以当第一次调用get方法时输入随意參数为100方法返回”Hello”,第二次调用时输入随意參数200返回值”World”。 String result = mock.get(100) + " " + mock.get(200); // verfiy 验证的时候也可将參数指定为anyInt()匹配器,那么它将不关心调用时输入的參数的详细參数值。 verify(mock, times(2)).get(anyInt());
assertEquals("Hello World", result);
/* 注意:假设使用了參数匹配器。那么全部的參数须要由匹配器来提供,否则将会报错。 */
} /**
* 參数匹配器--Argument matchers test2.
*/
@SuppressWarnings("unchecked")
@Test
public void argumentMatchersTest2() {
Map<Integer, String> mapMock = mock(Map.class);
when(mapMock.put(anyInt(), anyString())).thenReturn("world");
mapMock.put(1, "hello");
// 注:在最后的验证时假设仅仅输入字符串”hello”是会报错的,必须使用Matchers 类内建的eq方法。 // 假设将anyInt()换成1进行验证也须要用eq(1)。
verify(mapMock).put(anyInt(), eq("hello"));
} /**
* 3.Mock对象的行为验证--Verify test.
*/
@Test
public void verifyTest() {
List<String> mock = mock(List.class);
List<String> mock1 = mock(List.class); when(mock.get(0)).thenReturn("hello");
mock.get(0);
mock.get(1);
mock.get(2);
mock1.get(0);
/* 方法的调用不关心是否模拟了get(2)方法的返回值。仅仅关心mock 对象后,是否运行了mock.get(2),假设没有运行。測试方法将不会通过。 */
verify(mock).get(2); // 验证对象mock是否调用了get(2)方法
verify(mock, never()).get(3); // 方法中能够传入never()方法參数来确认mock.get(3)方法不曾被运行过
/* 确认mock1对象没有进行不论什么交互===>測试不通过 */
verifyNoMoreInteractions(mock1); // 将其放在 mock1.get(0);之前就可以通过。
} /**
* 验证方法的调用顺序.
*/
@Test
public void testInvokeOrder() {
List<String> firstMock = mock(List.class);
List<String> secondMock = mock(List.class); firstMock.add("was called first");
firstMock.add("was called first");
secondMock.add("was called second");
secondMock.add("was called third"); /* 假设mock方法的调用顺序和InOrder中verify的顺序不同。那么測试将运行失败。 */ InOrder inOrder = inOrder(secondMock, firstMock);
inOrder.verify(firstMock, times(2)).add("was called first");
inOrder.verify(secondMock).add("was called second");
// 由于在secondMock.add("was called third")之后已经没有多余的方法调用了。
inOrder.verify(secondMock).add("was called third");
inOrder.verifyNoMoreInteractions();// 表示此方法调用后再没有多余的交互
} /**
* 自己定义Answer接口(方法预期回调接口)的应用
*/ @Test
public void customAnswerTest() {
List<String> mock = mock(List.class);
when(mock.get(4)).thenAnswer(new Answer() {
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Integer num = (Integer) args[0];
if (num > 3) {
return "yes";
}
throw new RuntimeException();
}
});
System.out.println(mock.get(4));
} /**
* 利用ArgumentCaptor(參数捕获器)捕获方法參数进行验证
*/
@Test
public void argumentCaptorTest() {
List mock = mock(List.class);
List mock2 = mock(List.class);
mock.add("John");
mock2.add("Brian");
mock2.add("Jim");
/*
* 首先构建ArgumentCaptor须要传入捕获參数的对象,样例中是String。接着要在 verify 方法的參数中调用argument.capture()方法来捕获输入的參数, <br> 之后
* argument变量中就保存了參数值,能够用argument.getValue()获取。
*/
ArgumentCaptor argument = ArgumentCaptor.forClass(String.class);
verify(mock).add(argument.capture());
assertEquals("John", argument.getValue());
verify(mock2, times(2)).add(argument.capture()); assertEquals("Jim", argument.getValue());
/* argument.getAllValues()。它将返回參数值的List。 */
assertArrayEquals(new Object[] { "John", "Brian", "Jim" }, argument.getAllValues().toArray());
} /**
* Spy-对象的监视<br>
* Mock 对象仅仅能调用stubbed 方法。调用不了它真实的方法。 但Mockito 能够监视一个真实的对象。这时对它进行方法调用时它将调用真实的方法。<br>
* 同一时候也能够stubbing 这个对象的方法让它返回我们的期望值。 另外不论是否是真实的方法调用都能够进行verify验证。<br>
* 和创建mock对象一样。对于final类、匿名类和Java的基本类型是无法进行spy的。
*/
@Test
public void spyTest2() {
List list = new LinkedList();
List spy = spy(list);
// optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);
// using the spy calls real methods
spy.add("one");
spy.add("two");
// prints "one" - the first element of a list
System.out.println(spy.get(0));
// size() method was stubbed - 100 is printed
System.out.println(spy.size());
// optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");
} }

二、注解用法

Mockito对Annotation的支持

Mockito 支持对变量进行注解,比如将mock 对象设为測试类的属性,然后通过注解的方式@Mock 来定义它。这样有利于降低反复代码。增强可读性,易于排查错误等。除了支持@Mock,Mockito支持的注解还有@Spy(监视真实的对象),@Captor(參数捕获器),@InjectMocks(mock对象自己主动注入)。

Annotation的初始化仅仅有Annotation还不够,要让它们工作起来还须要进行初始化工作。初始化的方

法为:MockitoAnnotations.initMocks(testClass)參数testClass是你所写的測试类。普通情况下在Junit4的@Before 定义的方法中运行初始化工作,例如以下:

@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}

除了上述的初始化的方法外,还能够使用Mockito 提供的Junit Runner:

MockitoJUnitRunner这样就省略了上面的步骤。

@RunWith(MockitoJUnit44Runner.class)
public class ExampleTest {
...
}

@Mock 注解

使用@Mock注解来定义mock对象有例如以下的长处:

1. 方便mock对象的创建

2. 降低mock对象创建的反复代码

3. 提高測试代码可读性

4. 变量名字作为mock对象的标示。所以易于排错

@Mock注解也支持自己定义name 和answer属性。以下是官方给出的@Mock使用的样例:

public class ArticleManagerTest extends SampleBaseTestCase {
@Mock
private ArticleCalculator calculator;
@Mock(name = "dbMock")
private ArticleDatabase database;
@Mock(answer = RETURNS_MOCKS)
private UserProvider userProvider;
private ArticleManager manager;
@Before
public void setup() {
manager = new ArticleManager(userProvider, database,
calculator);
}
}
public class SampleBaseTestCase {
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
}

@Spy 注解

Spy的用法请參阅前面的章节,在此不再赘述。以下是用法:

public class Test{
@Spy
Foo spyOnFoo = new Foo();
@Before
public void init(){
MockitoAnnotations.initMocks(this);
}
...
}

@Captor 注解

@Captor是參数捕获器的注解,有关用法见前章。通过注解的方式也能够更便捷

的对它进行定义。使用样例例如以下:

public class Test {
@Captor
ArgumentCaptor<AsyncCallback<Foo>> captor;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void shouldDoSomethingUseful() {
// ...
verify(mock.doStuff(captor.capture()));
assertEquals("foo", captor.getValue());
}
}

@InjectMocks 注解

通过这个注解,可实现自己主动注入mock 对象。

当前版本号仅仅支持setter 的方式进行

注入,Mockito 首先尝试类型注入,假设有多个类型同样的mock 对象。那么它

会依据名称进行注入。当注入失败的时候Mockito不会抛出不论什么异常,所以你可

能须要手动去验证它的安全性。

例:

@RunWith(MockitoJUnit44Runner.class)
public class ArticleManagerTest {
@Mock
private ArticleCalculator calculator;
@Mock
private ArticleDatabase database;
@Spy
private UserProvider userProvider = new ConsumerUserProvider();
@InjectMocks
private ArticleManager manager = new ArticleManager();
@Test
public void shouldDoSomething() {
manager.initiateArticle();
verify(database).addListener(any(ArticleListener.class));
}
}

上例中, ArticleDatabase 是ArticleManager 的一个属性, 由于

ArticleManager 是注解@InjectMocks 标注的。所以会依据类型自己主动调用它的

setter方法为它设置ArticleDatabase

Mockito的简单使用方法演示样例的更多相关文章

  1. CSS3中transform,transition和animation的简单介绍和使用方法演示样例

    transform是一个属性,本质跟width,height是一样的,加上transform也就是为类添加一个变换属性. transition是一个属性.它是用来控制过渡效果的,由于用transfor ...

  2. C#开发Unity游戏教程循环遍历做出推断及Unity游戏演示样例

    C#开发Unity游戏教程循环遍历做出推断及Unity游戏演示样例 Unity中循环遍历每一个数据,并做出推断 非常多时候.游戏在玩家做出推断以后.游戏程序会遍历玩家身上大量的所需数据,然后做出推断. ...

  3. Java 8 时间日期库的20个使用演示样例

    除了lambda表达式,stream以及几个小的改进之外,Java 8还引入了一套全新的时间日期API,在本篇教程中我们将通过几个简单的任务演示样例来学习怎样使用Java 8的这套API.Java对日 ...

  4. Eureka 的 Application Client client的执行演示样例

            上篇以一个 demo 演示样例介绍了 Eureka 的 Application Service 客户端角色.今天我们继续了解 Eureka 的 Application Client 客 ...

  5. C++ Primer中文本查询演示样例Query的实现

    近期在看C++ Primer复习C++的语法,看到书中15.9章中的文本查询演示样例时,认为设计得非常不错,于是便动手照着实现了一个,改动了非常久最终执行成功了,从中也学习到了非常多的语法.以下把实现 ...

  6. HBase总结(十一)hbase Java API 介绍及使用演示样例

    几个相关类与HBase数据模型之间的相应关系 java类 HBase数据模型 HBaseAdmin 数据库(DataBase) HBaseConfiguration HTable 表(Table) H ...

  7. Introspector(内省)简单演示样例 与 简单应用

    简单演示样例: package com.asdfLeftHand.test; import java.beans.BeanDescriptor; import java.beans.BeanInfo; ...

  8. JBoss 系列九十六:JBoss MSC - 简介及一个简单演示样例

    什么是 JBoss MSC JBoss MSC 即 JBoss Modular Service Container,是第三代 JBoss 产品 JBoss 7和WildFfly的内核,JBoss MS ...

  9. Thrift的安装和简单演示样例

    本文仅仅是简单的解说Thrift开源框架的安装和简单使用演示样例.对于具体的解说,后面在进行阐述. Thrift简述                                           ...

随机推荐

  1. CentOS6 自己动手搭建开放NTP服务器

    第一步: 1. 安装NTP服务程序: [root@host ~]# rpm -qa | grep ntp #查询是否安装ntp服务程序 [root@host ~]# yum install -y nt ...

  2. Crashlytics Android 异常报告统计管理

    http://www.infoq.com/cn/articles/crashlytics-crash-statistics-tools 简介 Crashlytic 成立于2011年,是专门为移动应用开 ...

  3. docker部署xxl-job

    资源 xxl-job:1.9.1 docker:17.05.0-ce maven:3.5.0-jdk-8 tomcat:8.5.23.0 mysql:5.6.40 一.创建数据库 克隆项目到服务器下 ...

  4. 简单DP内容

    1. 最长上升子序列 [题目描述] 给定N个数,求这N个数的最长上升子序列的长度. [样例输入] 7 2 5 3 4 1 7 6 [样例输出] 4 第一种解法:时间复杂度O(n^2), 状态设计:DP ...

  5. hdu3404 Switch lights

    题目描述 题解: 首先,由$SG$定理得SG(x,y)=mex(SG(x',y)^SG(x,y')^SG(x',y'))(x'<x,y'<y) 这里的$SG(x,y)$叫$Nim$积. $ ...

  6. HUST软件与微电子学院第八届程序设计竞赛-小乐乐下象棋

    这题其实很简单,我们可以用一个bfs搜索出所有的,小于k步的,到不同点不同步数的方案数. 我们首先初始化,走到(0,0)点的时候,我们把步数设置为0,但是方法数设置为1,这是因为我们走零步,到一个点, ...

  7. 第二章:systemverilog声明的位置

    1.package 定义及从package中导入定义(***) verilog中,对于变量.线网.task.function的声明必须在module和endmodule之间.如果task被多个modu ...

  8. Django 多个字段关联同一外键

    # -*- coding: utf-8 -*- """ Tencent is pleased to support the open source community b ...

  9. 【BZOJ 3555】 [Ctsc2014]企鹅QQ(哈希)

    Description PenguinQQ是中国最大.最具影响力的SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志.群.即时通讯.相册.集市等丰富强大 ...

  10. Java日志实战及解析 - 引导

    日志是什么? 程序日志的作用 记录程序运行情况,程序员观察和调试使用 统计分析 日后审计 程序员,开发工程师,架构师等天天打交道. 实际中有4%的代码是日志! http://logging.apach ...