Mock&Spring集成
2015-11-27 16:49
519 查看
Mock&Spring集成
常规Mock单元测试
请参考上一篇文档Mockmock框架的功能性对比
http://jmockit.github.io/MockingToolkitComparisonMatrix.html从模拟支持特性上做了详细的对比,比如是否支持模拟static、构造函数等等。
集成测试
大部分Web应用项目基于Spring平台构建,集成测试主要关注点是Junit+Spring+Mock集成!从Spring项目2.x开始就有基于Junit的测试辅助包(Spring-test)!
重点关注引入Mock框架后Spring与其集成!
温馨提示:Jmockit作为本文代码示例的模拟框架,其它模拟选型框架的测试结果直接作为结论。
关注点
Mock测试框架是否能够和Spring完美集成?版本&升级(mock框架版本和Spring版本是否完全兼容,无包冲突,是否可升级,比如Spring从2.x->3.x->4.x)
内容&特性(mock框架提供的各种模拟策略特性能否和Spring-test提供的各种测试支持类兼容)
基于Spring的测试点
虚拟机运行环境版本: 1.7.0_601)基础包版本:
Spring:2.5.6/3.x.x/4.x.x, Junit:4.x
2)Mock选型:
Mockito:1.9.5, PowerMock-mockito-*: 1.5.5
Jmock:2.6.0
Jmockit:1.14
3)模拟测试用例
模拟Spring单例bean方法
模拟静态方法调用
备注:实际测试是分开多个测试Demo,spring+mockito
示例代码
UserService,StaticUserService,UserAction类请参考上一篇文档Mock静态公共方法模拟
package jmockit; import mockit.NonStrictExpectations; import mockit.Verifications; import org.junit.Test; import org.wit.service.StaticUserService; import org.wit.service.UserAction; public class MockForPublicStaticDemo { @Test public void demo() { new NonStrictExpectations(StaticUserService.class) { { StaticUserService.sayHello(anyString); result = "mock"; } }; // assertEquals("mock", StaticUserService.sayHello("real")); UserAction userAction = new UserAction(); userAction.executeForPublicStatic1("real"); new Verifications() { { StaticUserService.sayHello(anyString); times = 1; } }; } }
Spring Singleton Bean方法模拟
package jmockit; import mockit.NonStrictExpectations; import mockit.Verifications; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.wit.service.StaticUserService; import org.wit.service.UserAction; import org.wit.service.UserService; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class MockForSpringJunitDemo { @Autowired private UserAction userAction; @Autowired private UserService userService; @Test public void demo() throws Exception { new NonStrictExpectations(StaticUserService.class) { { StaticUserService.sayHello(anyString); result = "mock"; } }; userAction.executeForPublicStatic1("real"); new Verifications() { { StaticUserService.sayHello(anyString); times = 1; } }; } /** * * <pre> * 模拟bean的方法. * UserService sayHello模拟调用, sayHi为真实调用. * </pre> * * @throws Exception */ @Test public void beanDemo() throws Exception{ new NonStrictExpectations(userService) { { userService.sayHello(anyString); result = "mock"; } }; userAction.executeForPublic("hi"); new Verifications() { { userService.sayHello(anyString); times = 1; } }; } }
静态私有方法模拟
package jmockit; import static mockit.Deencapsulation.invoke; import mockit.Expectations; import mockit.Verifications; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.wit.service.StaticUserService; import org.wit.service.UserAction; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class MockForSpringJunitPrivateStaticDemo { @Autowired private UserAction userAction; @Test public void demo() throws Exception { new Expectations(StaticUserService.class) { { invoke(StaticUserService.class, "secreteSayHi", anyString); invoke(StaticUserService.class, "secreteSayHello", anyString); result = "mock"; } }; userAction.executeForPrivateStatic("real"); new Verifications() { { invoke(StaticUserService.class, "secreteSayHi", anyString); times = 1; invoke(StaticUserService.class, "secreteSayHello", anyString); times = 1; } }; } }
结论
方案:Mockito:1.9.5, PowerMock-mockito-*: 1.5.5Spring-test 3.x以上版本启用了新测试基类,并提供新的测试运行器(SpringJunit4ClassRunner.class), 它会和PowerMock提供的测试运行器(PowerMockRunner.class)产生冲突,如果选择PowerMockRunner会导致找不到Spring配置文件的错误发生;
Spring-test 2.5.6的测试基类AbstractDependencyInjectionSpringContextTests和PowerMock兼容,但此类在Spring3.x之后的版本中过时。
采用官方提供的PowerMockRule会产生虚拟机崩溃的错误详细日志见下文
2015-11-27 15:58:48,015 INFO context.TestContextManager - Could not instantiate TestExecutionListener class [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available. 2015-11-27 15:58:48,019 INFO context.TestContextManager - Could not instantiate TestExecutionListener class [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available. 2015-11-27 15:58:48,112 INFO xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml] 2015-11-27 15:58:48,191 INFO support.GenericApplicationContext - Refreshing org.springframework.context.support.GenericApplicationContext@361fc5a2: startup date [Fri Nov 27 15:58:48 GMT+08:00 2015]; root of context hierarchy # # A fatal error has been detected by the Java Runtime Environment: # # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000000291e2ba, pid=15700, tid=14928 # # JRE version: Java(TM) SE Runtime Environment (7.0_60-b13) (build 1.7.0_60-ea-b13) # Java VM: Java HotSpot(TM) 64-Bit Server VM (24.60-b09 mixed mode windows-amd64 compressed oops) # Problematic frame: # j java.lang.reflect.ReflectAccess.copyField(Ljava/lang/reflect/Field;)Ljava/lang/reflect/Field;+1 # # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows # # An error report file with more information is saved as: # D:\workspace\workspace-demos\mockito\hs_err_pid15700.log Compiled method (c2) 861 16 java.lang.Object::<init> (1 bytes) total in heap [0x0000000002969310,0x0000000002969540] = 560 relocation [0x0000000002969430,0x0000000002969440] = 16 main code [0x0000000002969440,0x00000000029694c0] = 128 stub code [0x00000000029694c0,0x00000000029694d8] = 24 oops [0x00000000029694d8,0x00000000029694e0] = 8 scopes data [0x00000000029694e0,0x00000000029694f0] = 16 scopes pcs [0x00000000029694f0,0x0000000002969520] = 48 dependencies [0x0000000002969520,0x0000000002969528] = 8 handler table [0x0000000002969528,0x0000000002969540] = 24 # # If you would like to submit a bug report, please visit: # http://bugreport.sun.com/bugreport/crash.jsp #
方案: Jmock:2.6.0,Jmockit:1.14
Jmock&Jmockit在测试运行器上选择Spring的测试运行器,和Spring各个版本兼容良好。
模拟Spring 单例Bean的方法和静态方法都能正常模拟,请关注静态私有方法和公共方法的差异。
QA
相关文章推荐
- leetcode--merge two sorted lists(java)
- JavaWeb学习篇之----自定义标签&&JSTL标签库详解
- 菜鸟学Java----局部定义的内部类
- java String类型的格式化
- Java -- 读取properties
- myeclipse更改字符集
- JavaSE+Thread
- 用eclipse修改web工程的访问路径
- Spring中,请求参数处理
- 实习过程学习(1):springMVC页面跳转
- Javassist Enhancement failed: model.AttendType; nested exception is org.hibernate.HibernateException
- Selenium等待元素的处理方法
- java.lang.ClassFormatError unrecognized class file version 解决办法
- dubbo + spring + mybaits 的pom文件列一
- Struts2_学习笔记(二)--------Namespace、Action、Path、
- spring切点表达式中的通配符
- Java 语言实现的八大排序算法
- Spring中AOP实例详解
- SpringMVC 3.2集成Spring Security 3.2集成mybaties
- 03 MyBitSet