spring中使用mockito
1 mockito介绍和入门
官方:https://github.com/mockito/mockito
入门:
5分钟了解Mockito http://liuzhijun.iteye.com/blog/1512780
Mockito:一个强大的用于 Java 开发的模拟测试框架 http://www.oschina.net/translate/mockito-a-great-mock-framework-for-java-development
2 spring中正常使用mockito
上demo代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:testApplicationContext.xml" })
public class SpringMockitoTest {
@Mock
private ApiService mockApiService;
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
when(mockApiService.test()).thenReturn("ok");
}
@Test
public void should_success_when_testApiService() {
String result = mockApiService.test();
Assert.assertEquals("ok", result);
}
}
@Component
public class ApiService {
@Autowired
private TestApiService testApiService;
public String test() {
String connect = testApiService.connect();
connect += "test";//test自己的业务
return connect;
}
}
@Component
public class TestApiService {
public String connect() {
return "error";
}
public String findFromDb() {
return "db_data";
}
}
正常使用spring和mockito中,我们把需要的mock的ApiService给mock掉,但是我们更想的是把TestApiService中的connect方法mock掉,这样就可以测试我们自己的代码,也就是ApiService中test方法自己的业务。
3 spring中mock任何容器内对象
上面的demo中,我们如何mock掉TestApiService中的test方法?
因为TestApiService是spring容器管理的bean,并且ApiService中使用到TestApiService,所以我们把ApiService中引用的TestApiService替换成我们的mock对象即可。
Spring框架有个反射工具ReflectionTestUtils,可以把一个对象中属性设置为新值,我们可以使用:
ReflectionTestUtils.setField(apiService, "testApiService", spyTestApiService);
把我们mock的testApiService放到apiService中,这样apiService调用就是我们mock的对象了;但是默认spring中apiService对象是代理对象,不能直接把值设置到属性上,所以我们自己写个小的工具类,在最后如下:
ReflectionTestUtils.setField(AopTargetUtils.getTarget(apiService), "testApiService", spyTestApiService);
完整demo:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:testApplicationContext.xml" })
public class SpringMockitoTest {
@Autowired
private ApiService apiService;
@Mock
private TestApiService spyTestApiService;
@Autowired
private TestApiService testApiService;
@Before
public void initMocks() throws Exception {
MockitoAnnotations.initMocks(this);
ReflectionTestUtils.setField(AopTargetUtils.getTarget(apiService), "testApiService", spyTestApiService);
when(spyTestApiService.connect()).thenReturn("ok");
}
@After
public void clearMocks() throws Exception {
ReflectionTestUtils.setField(AopTargetUtils.getTarget(apiService), "testApiService", testApiService);
}
@Test
public void should_success_when_testApiService() {
String result = apiService.test();
Assert.assertEquals("oktest", result);
}
}
@Component
public class ApiService {
@Autowired
private TestApiService testApiService;
public String test() {
String connect = testApiService.connect();
connect += "test";//test自己的业务
return connect;
}
}
@Component
public class TestApiService {
public String connect() {
return "error";
}
public String findFromDb() {
return "db_data";
}
}
public class AopTargetUtils {
/**
* 获取 目标对象
* @param proxy 代理对象
* @return
* @throws Exception
*/
public static Object getTarget(Object proxy) throws Exception {
if(!AopUtils.isAopProxy(proxy)) {
return proxy;//不是代理对象
}
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");
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;
}
}
最后就是注意测试之后要还原现场,把spring对象还原,尤其在跑maven test的时候,否则可能会影响其他人的测试。
spring中使用mockito的更多相关文章
- Spring Boot项目中使用Mockito
本文首发于个人网站:Spring Boot项目中使用Mockito Spring Boot可以和大部分流行的测试框架协同工作:通过Spring JUnit创建单元测试:生成测试数据初始化数据库用于测试 ...
- Velocity初探小结--Velocity在spring中的配置和使用
最近正在做的项目前端使用了Velocity进行View层的数据渲染,之前没有接触过,草草过了一遍,就上手开始写,现在又回头细致的看了一遍,做个笔记. velocity是一种基于java的模板引擎技术, ...
- Spring中Bean的作用域、生命周期
Bean的作用域.生命周期 Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).protot ...
- Spring中Bean的实例化
Spring中Bean的实例化 在介绍Bean的三种实例化的方式之前,我们首先需要介绍一下什么是Bean,以及Bean的配置方式. 如果 ...
- 模拟实现Spring中的注解装配
本文原创,地址为http://www.cnblogs.com/fengzheng/p/5037359.html 在Spring中,XML文件中的bean配置是实现Spring IOC的核心配置文件,在 ...
- Spring中常见的bean创建异常
Spring中常见的bean创建异常 1. 概述 本次我们将讨论在spring中BeanFactory创建bean实例时经常遇到的异常 org.springframework.beans.fa ...
- Spring中配置数据源的4种形式
不管采用何种持久化技术,都需要定义数据源.Spring中提供了4种不同形式的数据源配置方式: spring自带的数据源(DriverManagerDataSource),DBCP数据源,C3P0数据源 ...
- spring中InitializingBean接口使用理解
InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法. 测试程序如下: imp ...
- Quartz 在 Spring 中如何动态配置时间--转
原文地址:http://www.iteye.com/topic/399980 在项目中有一个需求,需要灵活配置调度任务时间,并能自由启动或停止调度. 有关调度的实现我就第一就想到了Quartz这个开源 ...
随机推荐
- SpringMVC配置入門
我的開發環境 開發工具: springsource-tool-suite-2.9.0 JDK版本: 1.6.0_29 tomcat版本:apache-tomcat-7.0.26 本文地址: ...
- FME之于规划CAD数据质量检测
最近琢磨规划CAD数据转换入库GIS方面的技术问题,看过一些前辈的文章/文献,对于使用FME WorkBench方面,有了一些了解,往往直接转换数据丢失比较严重,而且GIS对图形属性和空间拓扑比较严格 ...
- opengles tutorial
https://developer.apple.com/library/ios/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide ...
- Modifiers: virtual, override, new, abstract, sealed, internal
internal 声明类.类成员.接口或接口成员具有内部可见性. internal 修饰符使类.接口或成员仅在当前包中可见. 当前包之外的代码不能访问 internal 成员.只有在同一程序集的文件中 ...
- halcon 常用算子中文解释说明(随时更新)
select_contours_xld (Edges, SelectedContours, 'closed', 0, 0, 0, 0) 筛选闭合边缘曲线 sub_image (ImageConvert ...
- Oracle实例和Oracle数据库(Oracle体系结构)
--========================================== --Oracle实例和Oracle数据库(Oracle体系结构) --==================== ...
- ServiceStack.Redis之IRedisClient<第三篇>
事实上,IRedisClient里面的很多方法,其实就是Redis的命令名.只要对Redis的命令熟悉一点就能够非常快速地理解和掌握这些方法,趁着现在对Redis不是特别了解,我也对着命令来了解一下这 ...
- C#函数式编程之由函数构建函数
在面向对象的编程中,如果我们需要复用其他的类,我们可以通过继承来实现.而在函数式编程中我们也可以采取不同的方式来复用这些函数.今天的教程将会讲述两种方式,其中一个就是组合,将多个函数组合成为一个函数, ...
- Dynamic CRM 2013学习笔记(十二)实现子表合计(汇总,求和)功能的通用插件
上一篇 Dynamic CRM 2013学习笔记(十一)利用Javascript实现子表合计(汇总,求和)功能 , 介绍了如何用js来实现子表合计功能,这种方法要求在各个表单上添加js方法,如果有很多 ...
- Kali Linux Web 渗透测试视频教程— 第八课 nessus
Kali Linux Web 渗透测试视频教程— 第八课 nessus 文/玄魂 视频课程地址:http://edu.51cto.com/course/course_id-1887.html 目录 n ...