本文主要是提供了一种解决方案,用于解决spring管理的测试用例在mock过程中,如何有效管理mock宿主和mock实体,并优化mock方法
一、基础类
1、Sping配置基础
@ContextConfiguration(locations = { "classpath:spring.xml" })
public abstract class BaseServiceTest extends
AbstractTransactionalJUnit4SpringContextTests {
/**
* 日志器
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 确认已有异常被抛出
*/
protected void checkExceptionRaise() {
Assert.assertTrue("can't reach here, a exception should be raised",
false);
}
}
2、通用测试基类
public abstract class BaseTest<T> extends BaseServiceTest {
private final Set<MockField> mockFields = new HashSet<MockField>();
/**
* 既可 mock 接口也可以 mock 类
*/
protected final Mockery context = new JUnit4Mockery() {
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
/**
*
*/
@After
public void restoreField() {
context.assertIsSatisfied();
for (final MockField mockField : mockFields) {
ReflectionTestUtils.setField(mockField.getToMock(),
mockField.getFieldName(), mockField.getNativeValue());
}
}
/**
* 提取实体类型信息
*
* @return 实体类型信息
*/
private Class<T> extractGenericParameterInfo() {
for (Class<?> current = getClass(); (current != BaseTest.class)
|| (current != Object.class); current = current.getSuperclass()) {
final Type genericSuperType = current.getGenericSuperclass();
if (!(genericSuperType instanceof ParameterizedType)) {
continue;
}
final ParameterizedType genericSuperClass = (ParameterizedType) genericSuperType;
final Type[] actualTypes = genericSuperClass
.getActualTypeArguments();
if (actualTypes.length == 0) {
continue;
}
final Type firstType = actualTypes[0];
if (!(firstType instanceof Class)) {
continue;
}
@SuppressWarnings("unchecked")
final Class<T> firstClass = (Class<T>) firstType;
return firstClass;
}
throw new IllegalStateException("无法获取有效的模板参数信息");
}
/**
* @return
*/
private Object getMockHost() {
Object toMock = getToMock();
if (toMock != null) {
return toMock;
}
final Field[] fields = this.getClass().getDeclaredFields();
for (final Field field : fields) {
final Class<T> genericParameterInfo = extractGenericParameterInfo();
if (genericParameterInfo.isAssignableFrom(field.getType())) {
Assert.assertNull("重复的mock宿主", toMock);
toMock = ReflectionTestUtils.getField(this, field.getName());
}
}
Assert.assertNotNull("mock宿主不能为空", toMock);
return toMock;
}
/**
* @return mock宿主
*/
protected Object getToMock() {
return null;
}
/**
* 为本测试用例指定的mock宿主,通过<code>getToMock()</code>指定,设置指定类型的mock实体
*
* @param <E>
* mock实体类型
* @param typeToMock
* 用来mock的实体类型
* @return mock实体
*/
protected <E> E mock(final Class<E> typeToMock) {
final E mockObject = context.mock(typeToMock);
final Object toMock = getMockHost();
String fieldName = null;
final Field[] fields = toMock.getClass().getDeclaredFields();
for (final Field field : fields) {
if (typeToMock.isAssignableFrom(field.getType())) {
Assert.assertNull("重复的mock实体", fieldName);
fieldName = field.getName();
}
}
Assert.assertNotNull("无法定位mock实体", fieldName);
mock(toMock, fieldName, mockObject);
return mockObject;
}
/**
* mock对象
*
* @param <E>
* mock对象类型
*
* @param toMock
* mock宿主
* @param fieldName
* 属性名称
* @param typeToMock
* 用来mock的对象类型
* @return mock对象
*/
protected <E> E mock(final Object toMock, final String fieldName,
final Class<E> typeToMock) {
final E mockObject = context.mock(typeToMock);
mock(toMock, fieldName, mockObject);
return mockObject;
}
/**
* @param toMock
* 用来插入mock对象的大对象
* @param fieldName
* 属性名称
* @param mockObject
* mock对象
*/
protected void mock(final Object toMock, final String fieldName,
final Object mockObject) {
final MockField mockField = new MockField();
mockField.setFieldName(fieldName);
mockField.setNativeValue(ReflectionTestUtils
.getField(toMock, fieldName));
mockField.setToMock(toMock);
Assert.assertTrue("不允许重复mock", !mockFields.contains(mockField));
mockFields.add(mockField);
ReflectionTestUtils.setField(toMock, fieldName, mockObject);
}
/**
* 为本测试用例指定的mock宿主,通过<code>getToMock()</code>指定,设置指定类型的mock实体
*
* @param fieldName
* 指定的属性名称
*
* @param <E>
* mock实体类型
* @param typeToMock
* 用来mock的实体类型
* @return mock实体
*/
protected <E> E mock(final String fieldName, final Class<E> typeToMock) {
final E mockObject = context.mock(typeToMock);
mock(getToMock(), fieldName, mockObject);
return mockObject;
}
}
3、派生自该基类的测试类实例
public class XXXXTest extends BaseTest<XXXXX > {
@Autowired
private XXXXX xxxxx;
@Test
public void testTTTTTTT() {
final YYYYY mockYYYYY = mock(YYYYYY.class);
context.checking(new Expectations() {
{
oneOf(mockYYYYY).doSomething()
will(returnValue(true))
}
});
Assert.assertTrue(phaseManageBizImpl.TTTTTTT());
}
}
二、技术难点
1、mock对象的还原,能够使spring的对象不被单个测试用例破坏
如果不剥离注入到mock宿主中的mock实体,下次再次使用该mock宿主时,由于spring不会对bean再次进行初始化,因此第二次使用的mock宿主行为是不可控的。
2、使用反射简化mock接口
三、优势
1、使用@after和@before完成,不需要增加单个测试用例的工作量
2、获取mock实体时方法简单
final YYYYY mockYYYYY = mock(YYYYYY.class);
可以直接mock掉XXXXX中的YYYYY类型变量,不需要指定宿主和实体名字即可完成mock对象注入和剥离
3、能够通过指定属性名进行扩展
mock方法有多个overwrite,允许通过指定field那么来注入mock实体
分享到:
相关推荐
Classes contained in spring-mock.jar: org.springframework.mock.jndi.ExpectedLookupTemplate.class org.springframework.mock.jndi.SimpleNamingContext.class org.springframework.mock.jndi....
struts-junit spring-mock spring-test junit等的javadoc.jar格式的API文档,直接导入Eclipse/MyEclipse/Netbeans等IDE即可实现快速API查询。 包含以下文件: File name -------------------------------------- ...
在java web应用中,通过mock技术可以模拟spring容器,从而进行单元测试,详细可以参见本文
Spring针对J2EE的常用Web接口提供了Mock,这些组件被发布于spring-mock.jar,介绍如下: MockHttpServletRequest:HttpServletRequest接口的mock实现。 MockHttpServletResponse:HttpServletResponse接口的mock...
spring-mock-2.0.8.jar
spring-framework完整源代码(spring框架源码) 完整的Spring工程源码,工程内内包括spring各模块源码 以下为spring工程源码包结构: spring-src org.springframework aop,beans,cache,context,core,dao,ejb,...
spring.jar是包含有完整发布的单个jar包,spring.jar中包含除了 spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环境下才会用到spring-mock.jar来进行辅助测试,正式应用系统中是用不得这些类...
Mock 介绍及原理,前后端 Mock 方法 Mock 是一种测试技术,用于模拟某些不容易构造或者不容易获取的对象,以便测试。在实际工作中,可能会遇到依赖接口不通、异常数据难模拟、单元测试干扰等问题,引入 Mock 可以...
spring.jar 是包含有完整发布的单个jar包,spring.jar中包含除了spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环境下才会用到spring-mock.jar来进行辅助测试,正式应用系统中是用不得这些类...
可以用来Mock JAVA代码中的静态方法
基于Java探针的Mock框架
spring-framework完整源代码(spring框架源码) 完整的Spring工程源码,工程内内包括spring各模块源码 以下为spring工程源码包结构: spring-src org.springframework aop,beans,cache,context,core,dao,ejb,...
@MockBean,但允许您使用由您选择的库创建的模拟。 内容 特征 将 spock/mockito 创建的模拟注入测试用例 (, ) 扩展模拟和间谍配置 (, ) 在 spring 上下文中注册在配置/测试类上声明的模拟(只需将 @AutowiredMock @...
JavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源...
google c++ testing 框架 google mock 资料搜集