- 浏览: 461961 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (178)
- linux (25)
- java (31)
- eclipse (3)
- web (19)
- database (11)
- framework (7)
- spring (1)
- jbpm (1)
- error and solution (3)
- struts2 (3)
- hibernate (12)
- other (15)
- ubuntu (2)
- build tools (1)
- 服务器配置 (3)
- extjs (2)
- ssl相关 (1)
- 项目管理 (0)
- 软件测试 (0)
- java maven2 (2)
- Windows Server 2003 (1)
- glassfish (1)
- build tools,maven (2)
- Heritrix3 (1)
最新评论
-
lbs1026:
您好,卸载后怎么再装上去呢?
java中dll文件的加载和卸载。 -
mp19901204:
请教下,能通过js播放指定的影片吗。不刷新网页,用js直接调用 ...
Flv播放器 Vcastr3.0的用法参考 -
wiflish:
hanmiao 写道试了第壹個,好用。
使maven2在下载依赖包的同时下载其源代码包。 -
hanmiao:
试了第壹個,好用。
使maven2在下载依赖包的同时下载其源代码包。 -
chuanwang66:
请问Heritrix 3.1.0 你是怎么配置进Eclipse ...
Heritrix3.1.0RC1使用Cookie不能自动登录问题的一个解决办法
使用JMock来实现孤立测试(转)
我们在测试某类时,由于它要与其他类发生联系,因此往往在测试此类的代码中也将与之联系的类也一起测试了。这种测试,将使被测试的类直接依赖于其他 类,一旦其他类发生改变,被测试类也随之被迫改变。更重要的是,这些其他类可能尚未经过测试,因此必须先测试这些类,才能测试被测试类。这种情况下,测试 驱动开发成为空谈。而如果其他类中也引用了被测试类,我们到底先测试哪一个类?因此,在测试中,如果我们能将被测试类孤立起来,使其完全不依赖于其他类的 具体实现,这样,我们就能做到测试先行,先测试哪个类,就先实现哪个类,而不管与之联系的类是否已经实现。
虚拟对象(mock object)就是为此需要而诞生的。它通过JDK中的反射机制,在运行时动态地创建虚拟对象。在测试代码中,我们可以验证这些虚拟对象是否被正确地调用 了,也可以在明确的情况下,让其返回特定的假想值。而一旦有了这些虚拟对象提供的服务,被测试类就可以将虚拟对象作为其他与之联系的真实对象的替身,从而 轻松地搭建起一个很完美的测试环境。
JMock是帮助创建mock对象的工具,它基于Java开发,在Java测试与开发环境中有不可比拟的优势,更重要的是,它大大简化了虚拟对象的使用。
本文中,通过一个简单的测试用例来说明JMock如何帮助我们实现这种孤立测试。有三个主要的类,User,UserDAO,及 UserService。本文中,我们只需测试UserService,准备虚拟UserDAO。对于User,由于本身仅是一个过于简单的POJO,可 以不用测试。但如果你是一个完美主义者,也可以使用JMock的虚拟它。在这领域,JMock几乎无所不能。:)
User是一个POJO,用以在视图中传输数据及映射数据库。其代码如下:
package com.sarkuya.model;
public class User {
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
UserDAO负责与数据库打交道,通过数据库保存、获取User的信息。尽管我们可以不用知道JMock如何通过JDK的反射机制来实现孤立测试,但至
少应知道,JDK的反射机制要求这些在运行时创建的动态类必须定义接口。在使用JMock的环境中,由于我们要虚拟UserDAO,意味着UserDAO
必须定义接口。代码如下:
package com.sarkuya.dao;
import com.sarkuya.model.User;
public interface UserDAO {
public void saveUser(User user);
public User getUser(Long id);
}
UserService存有UserDAO的引用,通过其对外提供应用级的服务。相应地,我们先定义了其接口(尽管在本文中,作为被测试类,UserService不需要有接口,但如果以后此类需要被虚拟,也应该带有接口,基于此原因,我们也为其定义了接口)。
package com.sarkuya.service;
import com.sarkuya.dao.UserDAO;
import com.sarkuya.model.User;
public interface UserService {
public void setUserDAO(UserDAO userDAO);
public void saveUser(User user);
public User getUser(Long id);
}
可以看到,除了setUserDAO()外,其另外的方法与UserDAO一样。这是设计模式中门面模式的典型应用,应用只通过UserService提供服务,而UserService在内部通过调用UserDAO来实现相应的功能。
根据测试先行的原则,你应该先写测试,再编写实现。这里先编写实现的原因,主要是使读者更加清楚我们接着要测试什么。由于本文是着重介绍JMock的使用,加上UserServiceImpl比较简单,因此先列出其代码如下:
package com.sarkuya.service.impl;
import com.sarkuya.dao.UserDAO;
import com.sarkuya.model.User;
import com.sarkuya.service.UserService;
public class UserServiceImpl implements UserService {
private UserDAO userDAO;
public UserServiceImpl() {
}
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public User getUser(Long id) {
return userDAO.getUser(id);
}
public void saveUser(User user) {
userDAO.saveUser(user);
}
}
下面是UserService的测试代码:
package com.sarkuya.service;
import com.sarkuya.dao.UserDAO;
import com.sarkuya.model.User;
import com.sarkuya.service.impl.UserServiceImpl;
import junit.framework.*;
import org.jmock.Mock;
import org.jmock.MockObjectTestCase;
public class UserServiceTest extends MockObjectTestCase {
private UserService userService = new UserServiceImpl();
private Mock userDAO = null;
public UserServiceTest(String testName) {
super(testName);
}
protected void setUp() throws Exception {
userDAO = new Mock(UserDAO.class);
userService.setUserDAO((UserDAO)userDAO.proxy());
}
protected void tearDown() throws Exception {
}
public static Test suite() {
TestSuite suite = new TestSuite(UserServiceTest.class);
return suite;
}
public void testGetUser() {
User fakeUser = new User("John");
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(fakeUser));
User user = userService.getUser(1L);
assertNotNull(user);
assertEquals("John", user.getName());
}
public void testSaveUser() {
User fakeUser = new User("John");
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(fakeUser));
User user = userService.getUser(1L);
assertEquals("John", user.getName());
userDAO.expects(once()).method("saveUser").with(same(fakeUser));
user.setName("Mike");
userService.saveUser(user);
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(user));
User modifiedUser = userService.getUser(1L);
assertEquals("Mike", user.getName());
}
}
此段代码有几点应注意:
1、此测试类继承了JMock的MockObjectTestCase
2、private Mock userDAO = null;说明userDao是一个准备虚拟的对象
3、在setup()中,将userDAO.class传入Mock()后,再通过proxy()方法返回一个UserDAO的代理类实例(即虚拟对象实例),并赋值于userService
4、在testGetUser()方法中,如果我们先将第一行及第二行代码屏蔽掉,可以看出,这是一个真实环境下的测试代码。先获取一个User,
然后确认其非空值,再确认其姓名为“John”。此时,在真实环境下,这段代码要测试成功的前提必须是UserDAO已经连接到了数据库,然后返回一个
User后传给UserService。
但问题是,到目前为止,且不说UserDAO还未经历连接数据库这一系列繁琐而痛苦的过程,我们甚至还未实现UserDAO的接口!那么,为何加上第一行
及第二行代码后就可以了呢?这正是JMock的威力所在。先实例化一个测试用的fakeUser,然后通过一系列的指令,在第二行代码中告诉JMock应
该如何“做假”。尽管这句代码很长,我们可作如下理解:
1) userDAO.expects(once()):我们期望userDAO的某方法被执行一次,如果此方法未被执行,或者执行了二次以上,测试就不会通过
2) method("getUser"):这个期望被执行一次的方法名为userDAO.getUser()
3) with(eq(1L)):执行getUser()方法时,确认其传入的参数值为“1L”
4) will(returnValue(fakeUser)):上述条件均满足后,返回一个虚假的对象,即我们前面实例化的fakeUser
总体来说,当设定好第二行语句后,JMock就在后台监控着,确保userDAO.getUser()必须,且只被执行一次,且参数“1L”已经正确地传给了此方法,一旦这些条件被满足,就返回fakeUser。
而在第三行,User user = userService.getUser(1L)将触发所有这些条件,作为奖励,它接受了奖品fakeUser并赋值于user对象。而下面第四行及第五行均对此user对象进行测试,不通过才怪。
5) testSaveUser()方法中的原理类似。其思路是,将id为“1”的user从数据库中取出,将其名改为“Mike”,再存回数据库,然后再从数据库中取出此user,确保其名字已被改变。
第五行userDAO.expects(once()).method("saveUser").with(same(fakeUser))比较特殊。首
先,with(same(fakeUser))说明,传入参数必须是fakeUser此实例,尽管我们在下面的语句中通过user.setName
("Mike"),但只是改变了其name的属性,而fakeUser的实例引用并未发生改变,因此可以满足条件。其次,其后没有.will
(returnValue(fakeUser)),因为userDAO.saveUser()不需要返回任何对象或基本数据类型。
另外,当再次执行userDAO.expects()时,JMock将重设其监控条件。我们也可以通过userDAO.reset()来显式是清除监控条件。
通过以上实例代码及其说明,我们看出,用好JMock的关键是先设置监控条件,再写相应的测试语句。一旦设好监控条件后,在某段代码块执行完毕时, 如果监控条件未得到满足,或是没有通过expects()再次重设条件,或通过reset()来显式是清除监控条件,测试将无法通过。
以上介绍了JMock的基本使用方法。而这种基本用法,占了全面掌握JMock所需学习的知识70%以上。关于JMock的更多细节,感兴趣的读者可以访问JMock的网站进一步学习。
发表评论
-
《架构之美》笔记
2013-12-04 21:02 0美丽架构的特性: 1、概念完整性(来自于处理问题的一致性) ... -
【转】生产环境下JAVA进程高CPU占用故障排查
2013-11-01 16:36 1433转自: http://blog.chinaunix.net/ ... -
在maven生成eclipse文件时,使项目支持wtp的方式
2011-12-18 00:37 1234使项目能支持wtp: maven eclipse:ec ... -
解决Maven编译出现警告时,就提示编译失败的问题
2011-08-18 19:42 2101解决Maven编译出现警告时,就提示编译失败的问题 原因:m ... -
进入Glassfish3管理控制台太慢的解决办法
2011-07-07 14:53 1686解决办法:关闭Glassfish的网络链接。 配置方法 ... -
OSGi4.2规范的Bundle Manifest Headers列表
2010-01-22 17:40 2488OSGi4.2规范的Bundle Manifest ... -
VisualVM远程监控
2009-11-18 17:28 2626VisualVM是集成了多个JDK命令工具的一个可视化 ... -
maven-war插件打包war时,过滤掉指定文件或目录的配置方法
2009-09-09 11:53 17137<plugin> <artifac ... -
quartz中的CronTriggers表达式含义
2009-09-08 10:58 1039http://www.opensymphony.com/qua ... -
Spring-Security 2 中从数据库中读取权限的实现方式
2009-07-22 21:29 3551security的配置片段: < ... -
关于Bad version number in .class file错误
2009-04-01 10:54 1103出现Bad version number in .class ... -
maven报错。
2009-03-22 00:07 1629错误信息:[INFO] Required goal not f ... -
java处理视频
2009-01-12 22:42 3872目前绝大多数视频网站使用的格式是flv。格式可以任意位置播放, ... -
Xdoclet的标签及用法
2006-05-11 11:43 872参照链接: Xdoclet的标签及用法 -
原创:eclipse反编译插件Jadclipse介绍
2006-05-16 15:23 903jadclips插件网站:http://jadclipse.s ... -
ant中宏定义例子
2006-05-18 16:47 1599一个ant中用于编译的宏定义例子: 1 ... -
Google Web Toolkit
2006-05-22 14:12 842Google Web Toolkit (GWT) is a J ... -
[转]java基本类装入异常
2006-05-24 16:24 1135原文链接:http://www-128.ibm.co ... -
安装和卸载Mysql的windows系统服务
2006-05-26 15:20 1155安装mysql的windows系统服务: ${mysql.h ... -
通过java获取系统环境变量
2006-07-03 17:11 3665代码如下: 1 public static ...
相关推荐
本篇文章将探讨如何结合`FactoryBean`与Jmock库来实现动态Mock类的注入,以便于进行单元测试。 首先,我们需要了解`FactoryBean`的基本用法。`FactoryBean`的`getObject()`方法负责返回一个由工厂生产的对象,而...
- `JMock单元测试.doc`:可能包含具体的JMock使用示例和详细解释。 - `Jmock学习文档.docx`:更深入的JMock教程,可能包括高级用法和最佳实践。 - `Junit使用.ppt`:可能是一个关于JUnit基本用法和如何与JMock...
通过这个样本,开发者可以学习如何使用`TestNG`来编写和组织测试用例。 `jtester-0.8.2.zip`可能是一个辅助工具或者一个测试框架,用于简化测试过程。它可能包含了一些自动化测试工具或者测试管理功能,帮助开发者...
JMock是一种用于Java语言的Mock对象库,它主要用于单元测试中。它允许开发者创建虚拟对象(Mock对象)来模拟真实世界中复杂...随着对JMock使用的深入,可以逐渐体会到Mock技术在编写高质量、高可靠性的代码中的重要性。
1. **单元测试**:Jmock2.6是单元测试的理想选择,因为它可以帮助你专注于测试单个组件的行为,而无需关注其依赖的实现。 2. **隔离复杂依赖**:如果你的代码依赖于难以控制或不易构造的外部服务,Jmock可以帮助你...
在实际应用中,jMock常与其他测试框架如JUnit、TestNG等配合使用,通过它们的注解功能将模拟对象和测试用例紧密结合起来。同时,jMock也可以与EasyMock等其他模拟框架协同工作,提供更丰富的测试策略。 总结来说,...
在 JUnit 中,你可以使用 `jmock-junit3` 或 `jmock-junit4` 包,它们提供了一个 JUnit Rule,使得在测试类中使用 JMock 更加方便。 6. **版本信息** 这个压缩包中的 "jmock-1.2.0-jars" 提供的是 JMock 1.2.0 ...
要使用`jmock`进行单元测试,你需要: 1. 引入`jmock`库。 2. 创建模拟对象,定义期望的行为。 3. 在测试方法中,执行待测试的代码。 4. 使用`jmock`的验证机制检查期望是否满足。 ### 7. 文档资源 `doc`目录通常...
JMock是一个用于Java应用程序单元测试的工具,它允许程序员模拟对象的行为,以便在孤立的环境中测试代码。在这个资源包中,包含了英文版的《JMock_CookBook_EN.pdf》和中文版的《JMock_CookBook_CN.pdf》,为不同...
jMock与jUnit的集成非常紧密,通常我们会在jUnit测试类中使用jMock来模拟对象。以下是一个简单的示例: ```java import static org.jmock.Expectations.*; import org.junit.Test; import org.jmock.Mockery; ...
**JMock 概述** JMock 是一个Java平台上的单元测试框架,专门用于模拟对象...理解并熟练使用JMock,能够显著提升你的测试效率和代码质量。通过阅读和研究网上的博客和文档,你可以深入探索JMock的各种用法和最佳实践。
JMock可以轻松地与JUnit、TestNG等测试框架结合使用。在JUnit中,通常会在`@Before`方法中创建模拟对象,`@Test`方法中设置期望和验证,然后在`@After`方法中清理。 ### 源码分析 JMock的源码阅读可以帮助理解其...
在Spring测试中,我们可以使用JMock来模拟依赖于Spring容器的bean。例如,如果你有一个服务类依赖于一个DAO,你可以在测试中用JMock模拟DAO的行为,然后测试服务类的功能,而不实际访问数据库。这样可以提高测试速度...
在JMock中,当无法直接实例化或者不希望修改被测试类的源码时,CGLIB可以动态地生成被测试类的子类,从而实现模拟对象的创建。这对于那些没有默认构造函数或者final类的测试尤其有用。 JMock的使用方法主要包括以下...
总的来说,"maven+jmock" 主题涵盖了 Maven 项目的构建管理、单元测试的模拟技术以及源码理解和工具使用,这些都是软件开发过程中的关键环节。通过熟练掌握这些知识,开发者能够编写出更加健壮、易于维护的代码。
- `junit.jar`: 虽然JMock可以与任何测试框架一起使用,但这里可能包含JUnit是为了方便与JUnit进行集成,因为JMock常与JUnit一起用于单元测试。 - 可能还会有其他的依赖库,如`classloader-leak-prevention.jar`,...
不管是测试驱动开发或者是其它的开发模式,都会需要对代码进行单元测试,对于关联依赖关系少或者比较简单的类来说,直接使用JUnit就可以轻松的完成测试工作,但是对于关联到...在这里使用JMock来模拟那些不需要测试的类