JMockit 使用
1.使用介绍
传统mock方法的限制:
JDK Proxy必须实现接口
Cglib Proxy的class和方法不能是final限定的
对于静态方法无能为力
对非public方法无能为力,或者需要花比较大的代价进行反射处理
比较依赖于Ioc机制,对于new或工厂类管理的bean无法进行有效的测试
JMockit优点
JMockit项目基于 Java 5 SE 的 java.lang.instrument 机制,内部使用 ASM 库来修改Java的Bytecode,是一个能帮我们解决以上问题的轻量级框架,它允许你动态的改变已有的方法,这主要基于java 1.5的Instrumentation框架,允许你重定义private,static and final方法,甚至是no-arg constructors都能够并轻易的重定义,这样便可以使得JMockit能够适应几乎所有的设计。
使用mock的场景
真实对象有着不确定的行为
真实对象很难创建
真实对象的行为很难触发
真实对象响应缓慢
真实对象是用户界面
真实对象使用了回调机制
真实对象尚未存在
而对应的mock具有下面的功能
替换远程对象,如ESB、WEB Service对象等
替换复杂的对象
方便模块化开发
2.JMockit原理
JMockit是依赖JDK提供的instrument机制及ASM来实现其功能的,基本原理是这样的:
在JDK装入类的时候,由于我们设置也-javaagent,JDK会查看这个jar包的/META-INF/MANIFEST.MF文件,找到Premain-Class并加载这个类,然后调用这个类的premain方法将Instrument实现设置进去,然后JMockit就可以在类加载的时候做transformer,在做transformer的时候会通过ASM来动态改变字节码。
如果大家想有更深入的也解请在这里下载源代码。
3.JMockit运行环境要求
对于JDK5之后版本,不用设置;对于JDK5,需要配置jvm参数-javaagent:jmockit.jar
在 windows-perferences-java-installedJRES-default vm argument 中设置
-javaagent:D:\xx\xx\jmockit.jar
4.JMockit使用实例
关键词:如何mock一个类的方法、Expectations
源类清单
public class DateUtil {
private int type;
public static final String getCurrentDateStr() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(DateUtil.now());
}
public static final String getCurrentDateStrByFormatType(int type) {
if (type == 1) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
return sdf.format(DateUtil.now());
} else {
return DateUtil.getCurrentDateStr();
}
}
public static final Date now() {
return new Date();
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
单元测试类清单1
public class DateUtilTest {
/**
* Mock某个类方法
*/
@Test
public void testGetCurrentDateStr() {
//DateUtil.class,要Mock的类
new Expectations(DateUtil.class) {
{
//要Mock的方法now,其他方法DateUtil.class
DateUtil.now();
//期望方法返回的结果
result = mockDate();
}
};
Assert.assertEquals("2010-07-22 15:52:55", DateUtil.getCurrentDateStr());
}
/**
* Mock 某个类方法根据不同参数返回不同值
*/
@Test
public void testGetCurrentDateStrByFormatType() {
new Expectations(DateUtil.class) {
{
DateUtil.getCurrentDateStrByFormatType(anyInt);
result = new Delegate() {
public String getCurrentDateStrByFormatType(int type) {
if (type == 1) {
return "2010/07/22 15:52:55";
} else {
return "2010-07-22 15:52:55";
}
}
};
}
};
Assert.assertEquals("2010-07-22 15:52:55", DateUtil.getCurrentDateStrByFormatType(2));
}
public static Date mockDate() {
Calendar c = Calendar.getInstance();
c.set(2010, 6, 22, 15, 52, 55);
return c.getTime();
}
}
小结
Expectations:一个Expectations块是给定测试方法中将会涉及到的mock项中,预期将要被调用的方法或构造函数。一个Expectations可以包含多个预期的要执行方法(mock),但不必包含所有预期会被调用的方法。在Expectations中;除了可以指定预期的方法外,还可以指定方法的参数的精确值或约束行为(满足某个断言);同时Expectations中还可以指定该方法预期的返回值(如果有)或预期抛出的异常。Expectations(.class){}这种方式只会模拟区域中包含的方法,这个类的其它方法将按照正常的业务逻辑运行,上面的例子,定义了一个mock类DateUtil,同时在Expectation中定义了预期会被调用的方法now,以及now方法的返回值,这种方式还有种等价实现方式,使用@Mocked标签
@Test
public void testGetCurrentDateStr(@Mocked(methods="now")DateUtil dateUtil) {
//DateUtil.class,要Mock的类
new Expectations() {
{
//声明要Mock的方法(注:其它方法按照正常的业务逻辑运行)
DateUtil.now();
//期望方法返回的结果
result = mockDate();
}
};
Assert.assertEquals("2010-07-22 15:52:55", DateUtil.getCurrentDateStr());
}
case-2
关键词:service dao @Mocked
源类清单
public interface P4psettleDayService {
public List<DaySyncVerifyDO> getDaySyncVerifyNotSuccessList();
public void updataStatusById(Integer id,String status);
}
单元测试类清单
@TestCaseInfo(contextKey = "P4PSettleServicesLocator", defaultRollBack = false)
public class P4psettleDayServiceImplTest extends BaseTestCase {
private P4psettleDayService p4psettleDayService;
public void setP4psettleDayService(P4psettleDayService p4psettleDayService) {
this.p4psettleDayService = p4psettleDayService;
}
/**
* 此例子仅为说明如何Mock我们现有service或dao的部分方法
*/
@Test
public void testUpdataStatusById() {
new MockUp<P4psettleDayServiceImpl>(){
@Mock
public List<DaySyncVerifyDO> getDaySyncVerifyNotSuccessList(){
List<DaySyncVerifyDO> list = new ArrayList<DaySyncVerifyDO>();
DaySyncVerifyDO mockDO = new DaySyncVerifyDO();
mockDO.setId(111111);
list.add(mockDO);
return list;
}
};
//这里将返回我们mock的数据
List<DaySyncVerifyDO> list = p4psettleDayService
.getDaySyncVerifyNotSuccessList();
if (list != null && list.size() > 0) {
for (DaySyncVerifyDO item : list) {
//这里执行原有的方法
p4psettleDayService.updataStatusById(item.getId(),
DayEnum.DAYSYNCVERIFY_STATUS_SUCCESS.getValue());
}
}
}
}
小结
上面单元测试代码没有实际意义,只是说明如果我们希望mock spring注入的service或dao的一个或多个方法,就可采用上述方式
case-3
关键词:mock private方法 invoke
源类清单
还是第一个例子,Now方法是私有的
public class DateUtil {
......
private static final Date now() {
return new Date();
}
......
}
单元测试类清单
public class DateUtilTest {
/**
* Mock某个类私有方法
*/
@Test
public void testGetCurrentDateStr() {
//DateUtil.class,要Mock的类
new Expectations(DateUtil.class) {
{
//执行DateUtil的now方法
invoke(DateUtil.class,"now");
//期望方法返回的结果
result = mockDate();
}
};
Assert.assertEquals("2010-07-22 15:52:55", DateUtil.getCurrentDateStr());
}
小结
mock 某个类的私有方法,用invoke(mock的类或实例,方法名,方法的参数列表)
case-4
关键词:Verifications 想验证被Mock的类的某个方法是否被调用
单元测试类清单
/**
* 演示验证被Mock的类的某个方法是否被调用
*
* @author LeiSir
*/
public class ServiceTest {
@Mocked
Remote remote;
@Test
public void testDoFuncYes() {
Service service = new Service();
service.doFunc(true, 1);
new Verifications() {
{
remote.doSomething(anyInt);//表示这个方法会被执行
//remote.doSomething(1);//表示这个方法会被执行,而且参数是1;在当前case,会通过
//remote.doSomething(2);//表示这个方法会被执行,而且参数是2;在当前case,这个会不被通过
}
};
}
@Test
public void testDoFuncNo() {
Service service = new Service();
service.doFunc(false, 1);
new Verifications() {
{
remote.doSomething(anyInt);
times = 0;//调用次数,0表示上面方法不会被调用
}
};
}
private static class Remote {
public void doSomething(int a) {
}
}
private static class Service {
private Remote remote = new Remote();
public void doFunc(boolean flag, int a) {
if (flag) {
remote.doSomething(a);
}
}
}
}
小结
有时候我们想验证某个类的方法是否被正确调用的时候,上述Verifications就派上用场了
分享到:
相关推荐
**JMock使用文档** 在Java开发中,单元测试是一项至关重要的任务,它能确保代码的质量和可维护性。JMock是一款强大的模拟框架,专门用于Java应用程序的单元测试,特别是对于那些依赖于复杂外部接口或者服务的类。本...
在本文中,我们将深入探讨Jmock2.6的核心特性、使用场景以及如何在实际项目中应用。 **一、Jmock2.6概述** Jmock是一款开源的Java库,它基于JUnit构建,专门设计用来创建和验证对象交互。Jmock2.6是该库的一个版本...
要在项目中使用JMock,首先需要添加相应的依赖。对于Maven项目,可以在pom.xml文件中加入以下依赖: ```xml <groupId>org.jmock <artifactId>jmock-junit4 <version>2.8.4 <scope>test ``` 同时,由于JMock...
jMock 2.5.1.chm文件是一个帮助文档,包含了jMock框架的详细使用指南。通过这个文档,开发者可以学习如何创建和配置模拟对象,设置和验证期待,以及如何在JUnit等测试框架中集成jMock。 首先,创建模拟对象通常需要...
通过阅读这些文档,你可以更好地了解如何有效地使用`jmock`,解决你在测试过程中遇到的问题。 总结来说,`jmock-2.6.0-jars`是一个包含`jmock`库的压缩包,它提供了进行交互式单元测试的工具,特别是对于那些依赖于...
**JMock 概述** JMock 是一个Java平台上的单元测试框架,专门用于模拟对象...理解并熟练使用JMock,能够显著提升你的测试效率和代码质量。通过阅读和研究网上的博客和文档,你可以深入探索JMock的各种用法和最佳实践。
《JMock Cookbook资源整合》是关于Java测试领域中JMock库使用的详细指南,旨在帮助开发者更好地理解和运用这个强大的模拟框架。JMock是一个用于Java应用程序单元测试的工具,它允许程序员模拟对象的行为,以便在孤立...
本文将深入探讨jMock的核心概念、用法以及如何与JUnit结合使用。 一、jMock简介 jMock是基于Java的模拟库,它的设计目标是使单元测试变得更加简洁和清晰。传统的单元测试往往依赖于真实对象,但这种方式可能导致...
在 JUnit 中,你可以使用 `jmock-junit3` 或 `jmock-junit4` 包,它们提供了一个 JUnit Rule,使得在测试类中使用 JMock 更加方便。 6. **版本信息** 这个压缩包中的 "jmock-1.2.0-jars" 提供的是 JMock 1.2.0 ...
JMock的使用方法主要包括以下几个步骤: 1. **创建模拟对象**:使用`Mockery`类来创建模拟对象,如`Mockery context = new Mockery(); MyInterface mock = context.mock(MyInterface.class);` 2. **定义行为**:...
为了结合`FactoryBean`和Jmock,我们需要在`FactoryBean`的实现中使用Jmock来动态创建模拟对象。以下是一个简单的示例: ```java public class MockingFactoryBean implements FactoryBean<Object> { private ...
### jMock基本使用方法 #### 一、简介 jMock 是一个流行的 Java 框架,用于支持单元测试,特别是对于模拟对象(mock objects)的支持。通过 jMock,开发人员可以轻松地创建模拟对象来替代实际的对象依赖,从而在...
而JMock和EasyMock则是两种广泛使用的Java单元测试框架,它们允许开发者模拟对象的行为和交互,以便于测试复杂的系统。本资源包含JMock 2.5.1和EasyMock 3.0的库文件,使得开发者在进行单元测试时无需再四处寻找相关...
标题 "maven+jmock" 暗示了我们要讨论的是如何在 Maven 项目中使用 JMock 进行单元测试。Maven 是一个流行的构建自动化工具,用于管理项目的构建、依赖和文档,而 JMock 是一个 Java 代码模拟库,允许开发者在测试中...
Maven-Central / jmock / jmock-cglib 1.2.0 Maven-Central / org.apache.activemq / activemq-ra 5.2.05.1.0 Maven-Central / org.apache.maven.shared / maven-dependency-tree 1.21.1 Maven-Central / org.apache...
以下是如何使用 JMock 和 CGLIB 模拟无接口类的基本步骤: 1. 引入依赖:将这些 jar 文件添加到项目的类路径中,或者在使用 Maven 或 Gradle 的项目中,添加相应的依赖配置。 2. 创建模拟对象:使用 JMock 的 `...
在IT行业中,单元测试和集成测试是软件开发过程中的重要环节,确保代码的质量和稳定性。Spring框架为了方便开发者进行...深入理解和使用JMock及相关的测试框架,对于提升开发者的专业技能和项目成功率具有重要意义。
`jmock-2.6.0-RC2-javadoc.zip`和`jmock-2.5.1-javadoc.zip`包含的是`jmock`的API文档,可以帮助开发者理解和使用其API。`jmock-2.6.0-RC2-jars.zip`和`jmock-2.5.1-jars.zip`则包含了相应的库文件,可以直接在项目...