- 浏览: 1528945 次
- 性别:
- 来自: 厦门
博客专栏
-
Spring 3.x企业实...
浏览量:464654
文章分类
最新评论
-
JyeChou:
学习Spring必学的Java基础知识(1)----反射 -
hhzhaoheng:
...
《Spring4.x企业应用开发实战》光盘资料下载 -
renlongnian:
//assertReflectionEquals(user1, ...
单元测试系列之3:测试整合之王Unitils -
骑着蜗牛超F1:
huang_yong 写道我的经验是,只需定义三层:1.ent ...
Spring的事务管理难点剖析(2):应用分层的迷惑 -
wangyudong:
工具地址貌似更新了哦https://github.com/Wi ...
几种常用的REST webservice客户端测试工具
引述:Spring 的测试框架为我们提供一个强大的测试环境,解决日常单元测试中遇到的大部分测试难题:如运行多个测试用例和测试方法时,Spring上下文只需创建一次;数据库现场不受破坏;方便手工指定Spring配置文件、手工设定Spring容器是否需要重新加载等。但也存在不足的地方,基本上所有的Java应用都涉及数据库,带数据库应用系统的测试难点在于数据库测试数据的准备、维护、验证及清理。Spring 测试框架并不能很好地解决所有问题。要解决这些问题,必须整合多方资源,如DbUnit、Unitils、Mokito等。其中Unitils正是这样的一个测试框架。
使用unitils测试Service层
在进行服务层的测试之前,我们先来认识一下需要测试的UserServiceImpl服务类。UserServiceImpl服务类中拥有一个处理用户登录的服务方法,其代码如下所示。
UserService.java
UserServiceImpl需要调用DAO层的UserDao和LoginLogDao以及User和LoginLog这两个PO完成业务逻辑,User和LoginLog分别对应t_user和t_login_log这两张数据库表。
在用户登录成功后调用UserServiceImpl中的loginSuccess()方法执行用户登录成功后的业务逻辑。
这是一个需要访问数据库并存在数据更改操作的业务方法,它工作在事务环境下。下面是装配该服务类Bean的Spring配置文件。
baobaotao-service.xml
UserServiceImpl所关联的DAO类和PO类都比较简单,这里就不一一列出,读者可以参考本文附带光盘中的实例代码。在着手测试UserServiceImpl之前,需要先创建数据库表,相应的SQL脚本文件位于:D:\masterSpring\Chapter 16\schema目录下。
下面我们为UserServiceImpl编写一个简单的测试用例类,此时的目标是让这个基于Unitils测试框架的测试类运行起来,并联合Mockito框架创建Dao模拟对象。首先编写测试UserService#findUserByUserName()方法的测试用例,如代码清单16-37所示:
UserServiceTest.java
这里,我们让UserServiceTest直接继承于Unitils所提供的UnitilsJUnit4的抽象测试类,该抽象测试类的作用是让Unitils测试框架可以在JUnit 测试框架基础上运行起来。在①处,标注了一个类级的@SpringApplicationContext注解,这里Unitils将从类路径中加载Spring配置文件,并使用该配置文件启动Spring容器。在③处通过Mockito创建两个模拟DAO实例。在④-1处模拟测试数据并通过Mockito录制UserDao#findUserByUserName()行为。在④-2处实例化用户服务实例类,并在④-3处通过Spring测试框架提供的工具类org.springframework.test.util.ReflectionTestUtils为userService私有属性userDao赋值(ReflectionTestUtils是一个访问测试对象中私有属性非常好用的工具类)。在④-4处调用服务UserService#findUserByUserName()方法,并验证返回结果。在④-5处通过Mockito验证模拟userDao对象是否被调用,且只调用一次。最后在IDE中执行UserServiceTest测试用例,测试结果如图16-15所示。
从运行结果可以看出,我们已成功对UserServceTest.findUserByUserName()执行单元测试。下面我们通过Unitils提供的@DataSet注解来准备测试数据,并测试UserService# loginSuccess ()方法。BaobaoTao.SaveUsers.xls数据集如图16-16所示。
准备好了测试数据集之后,就可以开始为UserServiceImpl编写测试用例类,此时的目标是通过Unitils提供的@DataSet注解准备测试数据,来保证测试数据的独立性,避免手工通过事务回滚维护测试数据的状态。测试UserService#loginSuccess ()方法的代码如下所示。
代码清单16 38 UserServiceTest.java
在①处通过加载Unitils的@SpringApplicationContext 注解加载Spring配置文件,并初始化Spring容器。在②处通过@ SpringBean注解从Spring容器中获取UserService实例。在③处通过@DataSet注解从当前测试用例所在类路径中加载BaobaoTao.SaveUsers.xls数据集,并将数据集中的数据保存到测试数据库相应的表中。从上面的数据集中可以看出,我们为t_user表准备了两条用户信息测试数据。在④-1处从测试数据库中获取“tom”用户信息,模拟当前登录的用户。在④-2处设置当前“tom”用户的登录时间。在④-3处调用UserService#loginSuccess()方法,更新“tom”用户积分,并持久化到测试数据库中。在⑤处,验证“tom”用户当前积分是否是105分。完成测试用例的编写,最后在IDE中执行UserServiceTest测试用例,测试结果如图16-17所示。
从运行结果可以看出,我们已成功对UserServce#loginSuccess()执行单元测试。重复执行当前单元测试,测试结果仍然通过。细心的读者可能会有疑问,没有UserServce# loginSuccess()测试方法实施事务回滚,执行多次之后“tom”用户的积分不应该是105分,那为何测试还是通过呢?这是因为Unitils帮我们维护测试数据库中的数据状态,Unitils这个强大的魔力,归根于Unitils强大的数据集更新策略。到此我们成功完成UserServce单元测试。从上面为用户服务UserServce编写两个测试方法可以看出,对service层的测试,我们既可以采用JUnit+Unitils+Mockito组合,运用Mockito强大的模块能力,完成service层独立性测试,也可以采用JUnit+Unitils+Dbunit组合,运用Dbunit强大的数据库维护能力,完成service层+DAO层集成测试。
这些文章摘自于我的《Spring 4.x企业应用开发实战》的第16章,我将通过连载的方式,陆续在此发出。欢迎大家讨论。
使用unitils测试Service层
在进行服务层的测试之前,我们先来认识一下需要测试的UserServiceImpl服务类。UserServiceImpl服务类中拥有一个处理用户登录的服务方法,其代码如下所示。
UserService.java
package com.baobaotao.service; import com.baobaotao.domain.LoginLog; import com.baobaotao.domain.User; import com.baobaotao.dao.UserDao; import com.baobaotao.dao.LoginLogDao; @Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Autowired private LoginLogDao loginLogDao; public void loginSuccess(User user) { user.setCredits( 5 + user.getCredits()); LoginLog loginLog = new LoginLog(); loginLog.setUserId(user.getUserId()); loginLog.setIp(user.getLastIp()); loginLog.setLoginTime(user.getLastVisit()); userDao.updateLoginInfo(user); loginLogDao.insertLoginLog(loginLog); } … }
UserServiceImpl需要调用DAO层的UserDao和LoginLogDao以及User和LoginLog这两个PO完成业务逻辑,User和LoginLog分别对应t_user和t_login_log这两张数据库表。
在用户登录成功后调用UserServiceImpl中的loginSuccess()方法执行用户登录成功后的业务逻辑。
[1] 登录用户添加5个积分(t_user.credits)。
[2] 将登录用户的最后访问时间(t_user.last_visit)和IP(t_user.last_ip)更新为当前值。
[3] 在日志表(t_login_log)中为用户添加一条登录日志。
这是一个需要访问数据库并存在数据更改操作的业务方法,它工作在事务环境下。下面是装配该服务类Bean的Spring配置文件。
baobaotao-service.xml
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <context:component-scan base-package="com.baobaotao.service"/> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource" /> <tx:annotation-driven /> <!-- 使用aop/tx命名空间配置事务管理,这里对service包下的服务类方法提供事务--> <aop:config> <aop:pointcut id="jdbcServiceMethod" expression= "within(com.baobaotao.service..*)" /> <aop:advisor pointcut-ref="jdbcServiceMethod" advice-ref="jdbcTxAdvice" /> </aop:config> <tx:advice id="jdbcTxAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*"/> </tx:attributes> </tx:advice> </beans>
UserServiceImpl所关联的DAO类和PO类都比较简单,这里就不一一列出,读者可以参考本文附带光盘中的实例代码。在着手测试UserServiceImpl之前,需要先创建数据库表,相应的SQL脚本文件位于:D:\masterSpring\Chapter 16\schema目录下。
下面我们为UserServiceImpl编写一个简单的测试用例类,此时的目标是让这个基于Unitils测试框架的测试类运行起来,并联合Mockito框架创建Dao模拟对象。首先编写测试UserService#findUserByUserName()方法的测试用例,如代码清单16-37所示:
UserServiceTest.java
package com.baobaotao.service; import org.unitils.UnitilsJUnit4; import org.unitils.spring.annotation.SpringApplicationContext; import org.springframework.test.util.ReflectionTestUtils; import org.unitils.spring.annotation.SpringBean; import org.junit.Test; import com.baobaotao.domain.User; import java.util.Date; … @SpringApplicationContext({"baobaotao-service.xml", "baobaotao-dao.xml"}) //①加载Spring配置文件 public class UserServiceTest extends UnitilsJUnit4{ private UserDao userDao; //② 声明用户Dao private LoginLogDao loginLogDao; @Before //③ 创建Dao模拟对象 public void init(){ userDao = mock(UserDao.class); loginLogDao = mock(LoginLogDao.class); } @Test //④ 设置成为JUnit测试方法 public void findUserByUserName() { //④-1 模拟测试数据 User user = new User(); user.setUserName("tom"); user.setPassword("1234"); user.setCredits(100); doReturn(user).when(userDao).findUserByUserName("tom"); //④-2 实例化用户服务实例类 UserServiceImpl userService = new UserServiceImpl(); //④-3通过Spring测试框架提供的工具类为目标对象私有属性设值 ReflectionTestUtils.setField(userService, "userDao", userDao); //④-4 验证服务方法 User u = userService.findUserByUserName("tom"); assertNotNull(u); assertThat(u.getUserName(),equalTo(user.getUserName())); //④-5 验证交互行为 verify(userDao,times(1)).findUserByUserName("tom"); } }
这里,我们让UserServiceTest直接继承于Unitils所提供的UnitilsJUnit4的抽象测试类,该抽象测试类的作用是让Unitils测试框架可以在JUnit 测试框架基础上运行起来。在①处,标注了一个类级的@SpringApplicationContext注解,这里Unitils将从类路径中加载Spring配置文件,并使用该配置文件启动Spring容器。在③处通过Mockito创建两个模拟DAO实例。在④-1处模拟测试数据并通过Mockito录制UserDao#findUserByUserName()行为。在④-2处实例化用户服务实例类,并在④-3处通过Spring测试框架提供的工具类org.springframework.test.util.ReflectionTestUtils为userService私有属性userDao赋值(ReflectionTestUtils是一个访问测试对象中私有属性非常好用的工具类)。在④-4处调用服务UserService#findUserByUserName()方法,并验证返回结果。在④-5处通过Mockito验证模拟userDao对象是否被调用,且只调用一次。最后在IDE中执行UserServiceTest测试用例,测试结果如图16-15所示。
从运行结果可以看出,我们已成功对UserServceTest.findUserByUserName()执行单元测试。下面我们通过Unitils提供的@DataSet注解来准备测试数据,并测试UserService# loginSuccess ()方法。BaobaoTao.SaveUsers.xls数据集如图16-16所示。
准备好了测试数据集之后,就可以开始为UserServiceImpl编写测试用例类,此时的目标是通过Unitils提供的@DataSet注解准备测试数据,来保证测试数据的独立性,避免手工通过事务回滚维护测试数据的状态。测试UserService#loginSuccess ()方法的代码如下所示。
代码清单16 38 UserServiceTest.java
package com.baobaotao.service; import org.unitils.UnitilsJUnit4; import org.unitils.spring.annotation.SpringApplicationContext; import org.unitils.spring.annotation.SpringBean; import org.junit.Test; import com.baobaotao.domain.User; import java.util.Date; … @SpringApplicationContext({"baobaotao-service.xml", "baobaotao-dao.xml"}) //①加载Spring配置文件 public class UserServiceTest extends UnitilsJUnit4{ //② 从Spring容器中加载UserService实例 @SpringBean("userService") private UserService userService; @Test @DataSet("BaobaoTao.SaveUsers.xls")//③ 准备验证数据 public void loginSuccess() { User user = userService.findUserByUserName("tom"); //④-1 加载"tom"用户信息 Date now = new Date(); user.setLastVisit(now); //④-2 设置当前登录时间 userService.loginSuccess(user); //④-3 user登录成功,更新其积分及添加日志 User u = userService.findUserByUserName("tom"); assertThat(u.getCredits(),is(105)); //⑤ 验证登录成功之后,用户积分 } }
在①处通过加载Unitils的@SpringApplicationContext 注解加载Spring配置文件,并初始化Spring容器。在②处通过@ SpringBean注解从Spring容器中获取UserService实例。在③处通过@DataSet注解从当前测试用例所在类路径中加载BaobaoTao.SaveUsers.xls数据集,并将数据集中的数据保存到测试数据库相应的表中。从上面的数据集中可以看出,我们为t_user表准备了两条用户信息测试数据。在④-1处从测试数据库中获取“tom”用户信息,模拟当前登录的用户。在④-2处设置当前“tom”用户的登录时间。在④-3处调用UserService#loginSuccess()方法,更新“tom”用户积分,并持久化到测试数据库中。在⑤处,验证“tom”用户当前积分是否是105分。完成测试用例的编写,最后在IDE中执行UserServiceTest测试用例,测试结果如图16-17所示。
从运行结果可以看出,我们已成功对UserServce#loginSuccess()执行单元测试。重复执行当前单元测试,测试结果仍然通过。细心的读者可能会有疑问,没有UserServce# loginSuccess()测试方法实施事务回滚,执行多次之后“tom”用户的积分不应该是105分,那为何测试还是通过呢?这是因为Unitils帮我们维护测试数据库中的数据状态,Unitils这个强大的魔力,归根于Unitils强大的数据集更新策略。到此我们成功完成UserServce单元测试。从上面为用户服务UserServce编写两个测试方法可以看出,对service层的测试,我们既可以采用JUnit+Unitils+Mockito组合,运用Mockito强大的模块能力,完成service层独立性测试,也可以采用JUnit+Unitils+Dbunit组合,运用Dbunit强大的数据库维护能力,完成service层+DAO层集成测试。
引用
提示:在实际项目中,我们只对DAO做集成测试,在对Service层测试中,对所有的DAO都用Mockito模拟,也即只对Service层单元测试。
这些文章摘自于我的《Spring 4.x企业应用开发实战》的第16章,我将通过连载的方式,陆续在此发出。欢迎大家讨论。
发表评论
-
狂魔型代码改造记
2016-10-22 13:02 2185功能需求 统计员工指定月:在职员工数,入职员工数,离职员 ... -
关于JAR包版本冲突的几个应对招数总结
2016-08-02 12:05 9732概述 Javeer们一定遇到过NoSuchMethod ... -
关于Websphere 会话管理若干奇葩问题
2015-12-09 20:45 4485引言 由于最近 ... -
几种常用的REST webservice客户端测试工具
2015-07-30 16:11 9739引言 开发了Rest WebService服务后,如果方便快捷 ... -
如何通过项目配置文件指定Log4J的配置文件
2015-07-28 21:47 12847引言 在打造易于部署的WEB应用项目 一文中,我们介绍了如何对 ... -
打造易于部署的WEB应用项目
2015-07-27 16:46 3059概述 很多WEB应用的配置文件位于项目的类路径下(如WEB-I ... -
ROCA Resource-oriented Client Architecture
2014-03-21 18:16 1786ROCA Resource-oriented Client ... -
dbunit经典的NoSuchColumnException解决之道
2013-08-20 14:36 7366抱怨 dbunit这么多人用 ... -
一个常见的Spring IOC疑难症状
2013-07-25 14:14 5072Case 请看下面的IOC实例: 1)Aa ... -
mybatis3.1分页自动添加总数
2013-07-08 21:11 22867问题 1.mybatis默认分页是内存分页的,谁用谁崩溃啊! ... -
关于Idea testng单元测试乱码的解决
2013-07-02 10:50 14190问题 我是使用intel ... -
网络技术专业名词
2012-11-07 15:30 1553MRTG 求助编辑百科名片 Multi Router Tr ... -
HyperSQL 2.0
2012-11-01 15:15 1967HyperSQL 2.0于本月7日发布了。此次发布距HSQLD ... -
Rop开发手册(1):最简单的服务开放平台框架
2012-08-08 11:35 8637Rop概述 Rop是Rapid Open Pl ... -
ETL及BI开源工具
2012-08-01 16:17 56441. Kettle Kettle是一款 ... -
HMAC简介
2012-06-11 12:38 5669HMAC简介 HMAC的典型应用 ... -
学习Spring必学的Java基础知识(9)----HTTP请求报文
2012-06-09 16:02 13959引述要学习Spring框架的技术内幕,必须事先掌握一些基本的J ... -
Mockito
2012-06-07 16:40 7570Overview Packag ... -
关于权限管理的一点小思考
2012-05-26 15:32 2486做任何系统组织结构和权限管理是必不可少的,同时也是最重要的,实 ... -
学习Spring必学的Java基础知识(8)----国际化信息
2012-05-26 11:19 28499引述要学习Spring框架的 ...
相关推荐
综上所述,"使用Unitils测试DAO"的主题涵盖了如何利用Unitils库和DBUnit组件来创建可靠的DAO层测试,包括数据库的初始化、数据集的管理、断言的使用,以及自定义工具类的创建和源码分析。这种测试方法有助于提升代码...
Unitils 是一个强大的Java测试框架,它旨在简化单元测试的过程并提高测试的可维护性。该框架基于DbUnit和EasyMock,并与JUnit和TestNG兼容,提供了对数据库测试、Mock对象管理和Spring集成的支持。 在数据库测试...
unitils整合dbunit利用excel进行单元测试 包含mock以及整合spring进行测试
本教程将向您展示如何使用 Unitils 来编写单元测试,并介绍一些常见的单元测试技术。 断言应用 ---------- 在单元测试中,断言是非常重要的一部分。断言的目的是为了验证测试结果是否与预期结果相符。Unitils 提供...
这里提到的四个文件是Java开发中常用的单元测试框架和库,分别是JUnit、DBUnit、Unitils和Mockito。让我们逐一深入探讨它们的功能和使用方法。 **JUnit** 是Java领域中最广泛使用的单元测试框架,这里的`junit-4.11...
5. **使用 Unitils 进行测试** 在使用 Unitils 进行测试时,我们可以利用其提供的注解,例如 `@UsingDataSet` 来加载数据库数据,`@TestedObject` 或 `@InjectFields` 来注入测试对象。同时,配合 EasyMock,我们...
5. **DAO支持**:Unitils还提供了对各种ORM框架(如Hibernate、JPA)的集成,简化了DAO层的测试。它可以自动管理实体的持久化状态,无需手动调用flush和clear方法。 6. **代码覆盖率**:虽然Unitils本身并不直接...
一、Mybatis DAO层测试难点 在mybatis DAO层中,对数据库的单元测试存在一些难点: 1. 可重复性:每次运行单元测试,得到的数据是重复的独立的。 2. 独立性:测试数据与实际数据相互独立。 3. 数据库中脏数据...
10. **持久层测试**:支持对实体和会话工厂的验证,确保数据操作的正确性。 这个压缩包中的"unitils-3.3"可能包含了以下文件结构: - `unitils-3.3.jar`:主库文件,包含Unitils的核心功能。 - `unitils-dbunit....
Unitils 测试框架目的是让单元测试变得更加容易和可维护。Unitils 构建在DbUnit 与 EasyMock 项目之上并与JUnit 和TestNG 相结合。支持数据库测试,支持利用Mock 对象 进行测试并提供与Spring 和Hibernate 相集成。...
Unitils 是一个强大的Java开发框架,专为简化单元测试和集成测试而设计。它提供了对数据库、Spring框架以及其他模块的全面支持,使得测试过程更加高效和便捷。在深入探讨Unitils的功能之前,让我们先理解一下单元...
Unitils 是一个面向 Java 的测试工具集合,它提供了一系列增强单元测试的工具类。对于复杂的接口测试场景,Unitils 可以简化对象初始化、数据库操作等任务。 ##### 5.5 TestNG TestNG 是一个用于 Java 的测试框架,...
Unitils则是一个专注于简化单元测试的Java库,它提供了诸如数据库和持久层支持等功能。Groovy是Java平台上的动态语言,与Java代码可互操作,其语法简洁,易于编写。 描述中的 "bytesize.zip" 提到了一个用于处理...
总之,“改资源配准测试”是一项关键的IT实践,它涵盖了单元测试、数据库管理和自动化工具的使用。通过熟练掌握Unitils和DBUtils,开发者可以更有效地管理和测试项目中的资源,确保系统的稳定性和可靠性。而`chapter...
Unitils 模块 - 启动 Selenium Web 驱动程序以测试 Web 应用程序的简单方法。
16.6 使用unitils测试Service层 16.7 测试Web层 16.7.1 对LoginController进行单元测试 16.7.2 使用Spring Servlet API模拟对象 16.7.3 使用Spring RestTemplate测试 16.7.4 使用Selenium测试 16.8 小结 第17章 实战...
16.6 使用unitils测试Service层 16.7 测试Web层 16.7.1 对LoginController进行单元测试 16.7.2 使用Spring Servlet API模拟对象 16.7.3 使用Spring RestTemplate测试 16.7.4 使用Selenium测试 16.8 小结 第17章 实战...