使用 Mockito 单元测试 – 教程
tanyuanji@126.com
版本历史 |
|||
- |
- |
- |
- |
使用 Mockito 进行测试
该教程主要讲解 Mockito 框架在Eclipse IDE 中的使用
目录
2. 使用
存根(Stub) 和
模拟对象(Mock Object) 进行测试 2
2.2. 存根(Stub) vs. 模拟对象 (Mock) 2
1. 需求知识
该教程需要理解单元测试和熟悉JUnit 框架的使用。
如果您不熟悉 JUnit,请阅读 JUnit 教程。
2. 使用
存根(Stub) 和
模拟对象(Mock Object) 进行测试
2.1. 为什么需要模拟?
一个单元测试需要在隔离的环境下执行。如果可以的话需要消除其他依赖的服务影响。但实际上,软件中是充满依赖关系的.我们会基于service类写操作类,而service类又是基于数据访问类(DAOs)的,依次下去.
为了解决这个问题, 可以使用 存根 (Stub) 或者 模拟 (Mock) 对象的方法进行测试。
2.2. 存根(Stub) vs. 模拟对象 (Mock)
存根(Stub)类是实现了一个接口或者抽象类的类,可以在测试过程中使用该类,例如:
package cn.nsccsz.stub;
public
class TestStub {
static
interface USB {
void work();
}
static
class Mp3Stub implements USB {
@Override
public
void work() {
// code.
}
}
static
class Mp4Stub implements USB {
@Override
public
void work() {
// code.
}
}
}
一个模拟对象(mock object)是一个接口或者抽象类的虚拟实现。例如:
public
class TestMock {
static
interface USB {
void work();
}
@Test
public
void testMockObject() {
USB usb = Mockito.mock( USB.class );
usb.work();
}
}
存根和模拟对象都可以传递给其他的对象进行测试。你的一些单元测试可以测这些类的正确性等。利用存根对象或者模拟对象可以保证测试过程中不受到其他的影响。
存根对象需要自定义实现方法;
模拟对象只需要更少的代码和简单的配置。
以下的内容将详细介绍模拟对象的使用方法。
2.3. 行为测试 vs. 状态测试
Mock 对象允许你对行为进行测试。有一些测试不需要验证结果,但是需要检查某些方法是否被正确的参数调用过。这种测试为行为测试。
状态测试只是关注与结果是否正确,而行为测试能够判断一个应用调用结构以及层次。
2.4. 生成模拟对象
你们可以使用Mock 框架来生成模拟对象。Mock 框架允许你在运行期间创建对象,并且定义它的一些行为。
一个典型的例子就是使用模拟对象来模拟数据库DAO层。在生产环境上是使用运行的数据库,但是在单元测试环境中完全可以用模拟对象来模拟数据,确保单元测试的正确条件。这样就不需要依赖于外部的数据。
3. 模拟框架( Mock Framework)
比较流行的模拟框架有 EasyMock、jMock 和 Mockito。下面的列表是这些框架的链接。
# jMock
http://jmock.org/
# EasyMock
http://easymock.org/
# Mockito
http://code.google.com/p/mockito/
4. Mockito
4.1. 使用
Mockito 模拟对象
Mockito 是比较流行的模拟框架,可以与JUnit 联合起来测试。它允许你进行创建和配置模拟对象。
Mockito的官方网站: Mockito 主页.
4.2. 使用 Mockito
Mockito 支持使用 mock() 静态方法创建模拟对象。
同样也支持 @Mock注解方式,如果使用注解的方式,需要使用在初始化方法调用 MockitoAnnotation.InitMock( this ) 方法
For example, the following code demonstrate the usage of Mockito to test a class called ClassToTest.
例如,下面的例子就是使用 Mockito 进行对类 ClassToTest 的单元测试。
public
class MockitoTest {
@Mock
MyDatabase databaseMock;
@Before
public
void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public
void testQuery() {
// 需要测试的类
ClassToTest t = new ClassToTest(databaseMock);
// 调用方法
boolean check = t.query("* from t");
// 验证结果
assertTrue(check);
// 模拟对象是否调用了该方法
Mockito.verify( databaseMock ).query("* from t");
}
提示
可以使用静态导入方法调用方法 mock()
4.3. Mockito的限制
Mockito 以下的类型不能进行构造:
- 终态类(final classes)
- 匿名类(anonymous classes)
- 基本数据类型(primitive types)
4.4. 模拟对象的配置
Mockito 可以使用 verify() 方法来确认某些方法是否被调用过.
when(....).thenReturn(....) 结构可以为某些条件给定一个预期的返回值.
@Test
public
void testList() {
List mock = Mockito.mock( List.class );
Mockito.when( mock.get( 0 ) ).thenReturn( 1 );
assertEquals( "预期返回1", 1, mock.get( 0 ) );
}
同样可以使用doReturn(object).when(kdskfsk).methodCall 结构
4.5. 验证模拟对象的行为
Mockito 跟踪了所有的方法调用和参数的调用情况。verify()可以验证方法的行为。
查看下面的例子:
@Test
public
void testMap() {
Map mock = Mockito.mock( Map.class );
Mockito.when( mock.get( "city" ) ).thenReturn( "深圳" );
// test code
assertEquals( "城市测试", "深圳", mock.get( "city" ) );
Mockito.verify(mock).get( Matchers.eq( "city" ) );
Mockito.verify( mock, Mockito.times( 2 ) );
}
4.6. Spy
@Spy 或者方法 spy() 可以包含一个真实的对象. 每次调用,除非特出指定,委托给改真实对象的调用.
@Test
public
void testSpy() {
// Lets mock a LinkedList
List list = new
LinkedList();
list.add( "yes" );
List spy = Mockito.spy(list);
//You have to use doReturn() for stubbing
assertEquals( "yes", spy.get( 0 ) );
Mockito.doReturn("foo").when(spy).get(0);
assertEquals( "foo", spy.get( 0 ) );
}
@Test( expected = IndexOutOfBoundsException.class)
public
void testSpy2() {
// Lets mock a LinkedList
List list = new
LinkedList();
List spy = Mockito.spy(list);
// this would not work
// real method is called so spy.get(0)
// throws IndexOutOfBoundsException (list is still empty)
Mockito.when(spy.get(0)).thenReturn("foo");
assertEquals( "foo", spy.get( 0 ) );
}
5.1. 在 Android 使用 Mockito
Mockito 同样也可以在安卓平台上进行测试。
5.2. 安装
在 Android 测试项目中使用 Mockito。添加下面的包到Android 测试项目的 libs 目录
https://mockito.googlecode.com/files/mockito-all-1.9.5.jar
http://dexmaker.googlecode.com/files/dexmaker-1.0.jar
http://dexmaker.googlecode.com/files/dexmaker-mockito-1.0.jar
After you make the libraries available you can use Mockito in your tests.
接下来可以在你的测试项目中使用 Mockito 。
6. 感谢
感谢阅读该教程:
7. 链接和参考
7.1. Mockito 相关链接
Mockito 项目主页
Unit tests with Mockito - Tutorial
使用 Mockito 单元测试 – 教程的更多相关文章
- JUnit单元测试教程(翻译自Java Code Geeks)
JUnit单元测试教程--终极指南 JUnit单元测试教程终极指南 说明 单元测试简介 1 什么是单元测试 2 测试覆盖 3 Java中的单元测试 JUnit简介 1 使用Eclipse实现简单JUn ...
- mockito简单教程
注:本文来源:sdyy321的<mockito简单教程> 官网: http://mockito.org API文档:http://docs.mockito.googlecode.com/h ...
- JUnit + Mockito 单元测试
原 JUnit + Mockito 单元测试(二) 2015年01月05日 17:26:02 sp42a 阅读数:60755 版权声明:本文为博主原创文章,未经博主允许不得转载. https://bl ...
- mockito使用教程
一.什么是 Mock 测试 Mock 测试就是在测试过程中,对于某些不容易构造(如 HttpServletRequest 必须在Servlet 容器中才能构造出来)或者不容易获取比较复杂的对象(如 J ...
- JUnit + Mockito 单元测试(二)
摘自: http://blog.csdn.net/zhangxin09/article/details/42422643 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 入门 ...
- 使用 JUnit 进行单元测试 - 教程
tanyuanji@126.com 版本历史 JUnit 该教程主要讲解 JUnit 4.x 版本的使用,以及如何在Eclipse IDE 中如何使用JUnit 目录 tanyuanji@126. ...
- JUnit + Mockito 单元测试(二)(good)
import org.junit.Test; import org.mockito.Matchers; import org.mockito.Mockito; import java.util.Lis ...
- java 单元测试教程(junit)
单元测试概念:最小化测试 比如说你想测试某个类中的一个方法 优点:无须启动整个程序 clipse使用junit教程: (一)配置jar: 1.右键工程选择Build Path 在二级菜单选择 Add ...
- Mockito单元测试
Mockito简介 Mockito是一个单元测试框架,需要Junit的支持.在我们的项目中,都存在相当多的依赖关系,当我们在测试某一个业务相关的接口或则方法时,绝大多数时候是没有办法或则很难去添加所有 ...
随机推荐
- Android Studio builde.gradle 配置说明
//声明是Android应用程序 apply plugin: 'com.android.application' android { //编译SDK版本 compileSdkVersion 21 bu ...
- Codeforces 538E Demiurges Play Again(博弈DP)
http://codeforces.com/problemset/problem/538/E 题目大意: 给出一棵树,叶子节点上都有一个值,从1-m.有两个人交替从根选择道路,先手希望到达的叶子节点尽 ...
- BAT线下战争:巨额投资或培养出自己最大对手(包括美团、58、饿了么在内的公司都在计划推出自己的支付工具和金融产品,腾讯只做2不做O)
BAT线下战争:巨额投资或培养出自己最大对手 2015年10月12日09:49 <财经>杂志 我有话说(18人参与) 收藏本文 BAT大举投资线下公司,看似咄咄逼人 ...
- list append 总是复制前面的参数,而不复制最后一个参数
append 总是复制前面的参数,而不复制最后一个参数 (define a1 '(1 2 3)) (define a2 '(a b c)) (define x (append a1 a2)) x ; ...
- 黑马程序员_Java面向对象3_多态
5.面向对象_多态 多态定义:某一种事物存在的多种形态. 例:动物中猫,狗. 猫这个对象对应的类型是猫类型. 猫 x = new 猫(); 同时猫也是动物的一种,也可以把猫称为动物. 动物 y = n ...
- BaseAdapter自定义适配器——思路详解
BaseAdapter自定义适配器——思路详解 引言: Adapter用来把数据绑定到扩展了AdapterView类的视图组.系统自带了几个原生的Adapter. 由于原生的Adapter视图功能太少 ...
- poj 3666 Making the Grade(dp)
Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...
- python StringIO标准库基础学习
#标准库:StringIO提供类文件API文本缓冲区#作用:可以处理内存中的文本,有2种不同的实现:cStringIP版本用c编写提高速度,StringIO用python来提供可移植性,与其他字符串连 ...
- jquery Tabs选项卡切换
效果: HTML部分: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- 给那些因为Firebug而舍不得FireFox的朋友
Google Chrome浏览器调试 作为Web开发人员,我为什么喜欢Google Chrome浏览器 [原文地址:http://www.cnblogs.com/QLeelulu/archive/20 ...