前提:pom引用
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.0.5.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
</dependency> 背景:
方便后台开发自测接口,去除对象之间的复杂依赖,关注代码逻辑的正确性。
原理:
Mockito就是用Java提供的Dynamic Proxy API来实现的。 以下是简单的小demo:
package com.mock;

import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener; /**
* 所以测试类的基类
*
* @author tom_plus
* @date 2017-01-02-17:20
*/
@ContextConfiguration(locations = {"classpath:applicationContext-test.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners(listeners = {DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class})
public class AbstractServiceIT {
}
package com.mock.demo;

import com.AopTargetUtils;
import com.mock.AbstractServiceIT;
import com.springapp.bean.Teacher;
import com.springapp.service.TeacherService;
import com.springapp.service.TestService;
import com.springapp.utils.SessionContext;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;
import org.testng.Assert; import java.util.List; import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*; /**
* mock 使用demo
* 一个强大的用于 Java 开发的模拟测试框架
*
* @author tom_plus
* @date 2017-01-02-17:45
*/
public class MockServiceIT extends AbstractServiceIT{
@Mock
SessionContext sessionContext;
@Autowired
private TestService testService;
@Before
public void befTest() {
MockitoAnnotations.initMocks(this);
when(sessionContext.getId()).thenReturn(3);
try {
ReflectionTestUtils.setField(AopTargetUtils.getTarget(testService), "sessionContext", sessionContext);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
@Transactional
public void updateIT() throws Exception {
Teacher teacher = new Teacher();
teacher.settName("樱木花道");
int j = testService.update2(teacher);
System.out.println("result:"+j);
Assert.assertEquals(j,1,"更新成功");
} /**
* 参数匹配器,一旦使用参数匹配器,则方法中必须处处使用参数匹配器
*/
@Test
public void argumentMatcherTest(){
List<String> list = mock(List.class);
when(list.get(anyInt())).thenReturn("hello","world");
String result = list.get(0)+list.get(1);
System.out.println(result);
//verify 方法验证mock 对象的互动次数
verify(list,times(2)).get(anyInt());
verify(list,atLeast(2)).get(anyInt());
Assert.assertEquals("helloworld", result); } /**
* 使用异常处理void 方法
*/
@Test
public void stubbingForVoidMethod() {
List<String> list = mock(List.class);
doThrow(new RuntimeException("you are clear a list!")).when(list).clear();
list.clear();
}
}
package com;

import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AopProxy;
import org.springframework.aop.support.AopUtils; import java.lang.reflect.Field; /**
* Created by tom_plus on 2017/1/2.
*/
public class AopTargetUtils {
/**
* 获取 目标对象
*
* @param proxy 代理对象
* @throws Exception 默认spring中Service对象是代理对象,不能直接把值设置到属性上,所以我们自己写个小的工具类
*/
public static Object getTarget(Object proxy) throws Exception {
if (!AopUtils.isAopProxy(proxy)) {
return proxy;//不是代理对象
}
//jdk
if (AopUtils.isJdkDynamicProxy(proxy)) {
return getJdkDynamicProxyTargetObject(proxy);
} else { //cglib
return getCglibProxyTargetObject(proxy);
}
} private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");//获得字节码文件中的MethodInterceptor cglib$CALLBACK_0 变量
h.setAccessible(true);
Object dynamicAdvisedInterceptor = h.get(proxy);
Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
advised.setAccessible(true);
Object target = ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
return target;
} private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
h.setAccessible(true);
AopProxy aopProxy = (AopProxy) h.get(proxy);
Field advised = aopProxy.getClass().getDeclaredField("advised");
advised.setAccessible(true);
Object target = ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget();
return target;
}
}
												

mockito使用心得的更多相关文章

  1. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  2. NoSql数据库使用半年后在设计上面的一些心得

    NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...

  3. 我的MYSQL学习心得(二) 数据类型宽度

    我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  4. 我的MYSQL学习心得(三) 查看字段长度

    我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  5. 我的MYSQL学习心得(四) 数据类型

    我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...

  6. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  7. 我的MYSQL学习心得(六) 函数

    我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  8. 我的MYSQL学习心得(七) 查询

    我的MYSQL学习心得(七) 查询 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  9. 我的MYSQL学习心得(八) 插入 更新 删除

    我的MYSQL学习心得(八) 插入 更新 删除 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得( ...

随机推荐

  1. MySQL 常用SQL技巧和常见问题

    一.巧用正则表达式 二.巧用RAND() 提取随机行 利用rand() 的随机数功能,结合 order by 子句完成随机抽取某些行的功能. 三.利用 group by 的 with rollup 子 ...

  2. PROJ4初探(转并整理格式)

    PROJ4初探(转并整理格式) Proj4是一个免费的GIS工具,软件还称不上. 它专注于地图投影的表达,以及转换.采用一种非常简单明了的投影表达--PROJ4,比其它的投影定义简单,但很明显.很容易 ...

  3. ubuntu下MySQL中文乱码(新版本Mysql修改方法)

    前几天在开发的时候出现了中文查询阿里云服务器上的mysql的时候,查询出来的值为空,找了好久终于发现原因是ubuntu下的mysql无法识别中文,这就涉及到要调整编码格式啦!!!! 然后就在网上查了许 ...

  4. mysql 最大连接数 & 连接池

    MySQL最大连接数 关于最大连接数:http://mg123.lofter.com/post/1a5f3e_996f838 可以通过修改配置文件(默认/etc/my.cnf)中的"mysq ...

  5. [Linux]Linux系统调用列表

    本文列出了大部分常见的Linux系统调用,并附有简要中文说明. 以下是Linux系统调用的一个列表,包含了大部分常用系统调用和由系统调用派生出的的函数.这可能是你在互联网上所能看到的唯一一篇中文注释的 ...

  6. cisco-log

    每个日志消息被关联一个严重级别,用来分类消息的严重等级:数字越低,消息越严重.严重级别的范围从0(最高)到7(最低).  日志消息的严重级别,使用logging命令可以用数字或者名称来指定严重性.  ...

  7. AngularJS的JSONP服务

    有些页面的response中,包含了 Access-Control-Allow-Origin 这个header,说明可以进行跨域请求,如果没有包含这个header的页面可以利用JSONP进行跨域 sc ...

  8. C语言中字符串结束符'\0'

    转自:http://www.cnblogs.com/kaituorensheng/archive/2013/12/09/3464462.html 本质 '\0'就是8位的00000000,因为字符类型 ...

  9. [Android]Android开发入门之HelloWorld

    引言:在做Unity开发的时候,发现这么个问题,虽然Unity是跨平台的,能够进行Android,IOS,Web,PC等开发,但如果要实现一些稍微系统层的东西,还是需要通过通信,调用原系统的接口(自定 ...

  10. Visual Studio 2015 前瞻 属性初始化赋值!

    通常我们建立属性的时候如果带初始化值的时候我们经常会这样处理. class MyClass { private string _name = "hello world!"; pub ...