前提: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. 用JS做关灯游戏(初级)

    这是一个很有意思的游戏,可以试着玩下. <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...

  2. 利用js刷新页面方法

    1,reload 方法,该方法强迫浏览器刷新当前页面. location.reload(force) 如果该方法没有规定参数,或者参数是 false,它就会用 HTTP 头 If-Modified-S ...

  3. Python递归及斐波那契数列

    递归函数 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数.举个例子,我们来计算阶乘 n! = 1 * 2 * 3 * ... * n,用函数 fact(n)表示,可 ...

  4. EL算术表达式

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  5. Spark集群部署

    Spark是通用的基于内存计算的大数据框架,可以和hadoop生态系统很好的兼容,以下来部署Spark集群 集群环境:3节点 Master:bigdata1 Slaves:bigdata2,bigda ...

  6. HTML5实现网页的全屏切换

    使用HTML5提供的JavaScript Api可以实现主流浏览器的全屏和退出全屏操作,封装成进入全屏和退出全屏的函数如下: //进入全屏 function enterFullScreen() { v ...

  7. 倒计时simple 天时分秒

    new Date()new Date(yyyy,mth,dd,hh,mm,ss); //月从0计数 .getTime()返回的是一个long型的毫秒数 毫秒转成 秒 分 时 天 <div id= ...

  8. POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次

    Milk Patterns   Description Farmer John has noticed that the quality of milk given by his cows varie ...

  9. redis数据类型之—List

    (1)list 简单介绍 list是一个有序的字符串列表,是使用双向列表实现的,可以实现最新消息排行.消息队列等功能. (2) list 常用命令

  10. 2016 Multi-University Training Contest 3

    5/11 2016 Multi-University Training Contest 3官方题解 2016年多校训练第三场 老年选手历险记 暴力 A Sqrt Bo(CYD) 题意:问进行多少次开根 ...