单元测试工具 unitils
Unitils模块组件
Unitils通过模块化的方式来组织各个功能模块,采用类似于Spring的模块划分方式,如unitils-core、unitils-database、unitils-mock等。比以前整合在一个工程里面显得更加清晰,目前所有模块如下所示:
- unitils-core:核心内核包。
- unitils-database:维护测试数据库及连接池。
- unitils-DbUnit:使用DbUnit来管理测试数据。
- unitils-easymock:支持创建Mock和宽松的反射参数匹配。
- unitils-inject:支持在一个对象中注入另一个对象。
- unitils-mock:整合各种Mock,在Mock的使用语法上进行了简化。
- unitils-orm:支持Hibernate、JPA的配置和自动数据库映射检查。
- unitils-spring:支持加载Spring的上下文配置,并检索和Spring Bean注入。
Unitils的核心架构中包含Moudule和TestListener两个概念,类似Spring中黏连其他开源软件中的FactoryBean概念。可以看成第三方测试工具的一个黏合剂。整体框架如图16-4所示:
通过TestListener可以在测试运行的不同阶段注入某些功能。同时某一个TestListener又被一个对应的Module所持有。Unitils也可以看成一个插件体系结构,TestListener在整个Unitils中又充当了插件中扩展点的角色,从TestListener这个接口中我们可以看到,它可以在crateTestObject、before(after)Class、before(after)TestMethod、beforeSetup、afterTeardown的不同切入点添加不同的动作。
- Unitils配置文件
- unitils-defaults.properties:默认配置文件,开启所有功能。
- unitils.properties:项目级配置文件,用于项目通用属性配置。
- unitils-local.properties:用户级配置文件,用于个人特殊属性配置。
Unitils的配置定义了一般配置文件的名字unitils.properties和用户自定义配置文件unitils-local.properties,并给出了默认的模块及模块对应的className,便于Unitils加载对应的模块module。但是如果用户分别在unitils.properties文件及unitils -local.properties文件中对相同属性配置不同值时,将会以unitils-local.properties 的配置内容为主。
assertReflectionEquals:反射断言
在Java世界中,要比较现有两个对象实例是否相等,如果类没有重写equals()方法,用两个对象的引用是否一致作为判断依据。有时候,我们并不需要关注两个对象是否引用同一个对象,只要两个对象的属性值一样就可以了。在JUnit单元测试中,有两种测试方式进行这样的场景测试:一是在比较实体类中重写equals()方法,然后进行对象比较;二是把对象实例的属性一个一个进行比较。不管采用哪种方法,都比较烦锁,Unitils为我们提供了一种非常简单的方法,即使用ReflectionAssert.assertReflectionEquals方法, 如代码清单16-11所示:
package com.baobaotao.test;
import java.util.*;
import org.junit.Test;
import static org.unitils.reflectionassert.ReflectionAssert.*;
import static org.unitils.reflectionassert.ReflectionComparatorMode.*;
import com.baobaotao.domain.User; public class AssertReflectionEqualsTest {
@Test
public void testReflection(){
User user1 = new User("tom","1234");
User user2 = new User("tom","1234");
ReflectionAssert.assertReflectionEquals(user1, user2);
} }
集成Spring
Unitils 提供了一些在Spring 框架下进行单元测试的特性。Spring 的一个基本特性就是,类要设计成为没有Spring 容器或者在其他容器下仍然易于进行单元测试。但是很多时候在Spring 容器下进行测试还是非常有用的。
Unitils 提供了以下支持 Spring 的特性:
- ApplicationContext 配置的管理;
- 在单元测试代码中注入Spring 的Beans;
- 使用定义在Spring 配置文件里的Hibernate SessionFactory;
- 引用在Spring 配置中Unitils 数据源。
ApplicationContext 配置
可以简单地在一个类、方法或者属性上加上@SpringApplicationContext 注解,并用Spring的配置文件作为参数,来加载Spring应用程序上下文。下面我们通过实例来介绍一下如何创建ApplicationContext。
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.unitils.UnitilsJUnit4;
import org.unitils.spring.annotation.SpringApplicationContext;
import org.unitils.spring.annotation.SpringBean;
import com.baobaotao.service.UserService;
import static org.junit.Assert.*;
//①用户服务测试
public class UserServiceTest extends UnitilsJUnit4 { //①-1 加载Spring配置文件
@SpringApplicationContext({"baobaotao-service.xml", "baobaotao-dao.xml"})
private ApplicationContext applicationContext; //①-1 加载Spring容器中的Bean
@SpringBean("userService")
private UserService userService; //①-3 测试Spring容器中的用户服务Bean
@Test
public void testUserService (){
assertNotNull(applicationContext);
assertNotNull(userService.findUserByUserName("tom"));
}
}
…
在①-1处,通过@SpringApplicationContext 注解加载baobaotao-service.xml和baobaotao- dao.xml两个配置文件,生成一个Spring应用上下文,我们就可以在注解的范围内引用applicationContext这个上下文。在①-2处,通过@SpringBean注解注入当前Spring容器中相应的Bean,如实例中加载ID为“userService”的Bean到当前测试范围。在①-3处,通过JUnit断言验证是否成功加载applicationContext和userService。Unitils加载Spring上下文的过程是:首先扫描父类的@SpringApplicationContext注解,如果找到了就在加载子类的配置文件之前加载父类的配置文件,这样就可以让子类重写配置文件和加载特定配置文件。
细心的读者可能会发现,采用这种方式加载Spring应用上下文,每次执行测试时,都会重复加载Spring应用上下文。Unitils为我们提供在类上加载Spring应用上下文的能力,以避免重复加载的问题。
在父类BaseServiceTest里指定了Spring配置文件,Spring应用上下文只会创建一次,然后在子类SimpleUserServiceTest 里会重用这个应用程序上下文。加载Spring应用上下文是一个非常繁重的操作,如果重用这个Spring应用上下文就会大大提升测试的性能。
…
public class SimpleUserServiceTest extends BaseServiceTest { //① Spring容器中加载Id为"userService"的Bean
@SpringBean("userService")
private UserService userService1; //② 从Spring容器中加载与UserService相同类型的Bean
@SpringBeanByType
private UserService userService2; //③ 从Spring容器中加载与userService相同名称的Bean
@SpringBeanByName
private UserService userService; //④ 使用父类的Spring上下文
@Test
public void testApplicationContext(){
assertNotNull(applicationContext);
} @Test
public void testUserService(){
assertNotNull(userService.findUserByUserName("tom"));
assertNotNull(userService1.findUserByUserName("tom"));
assertNotNull(userService2.findUserByUserName("tom"));
}
}
…
在①处,使用@SpringBean 注解从Spring容器中加载一个ID为userService的Bean。在②处,使用@ SpringBeanByType注解从Spring容器中加载一个与UserService相同类型的Bean,如果找不到相同类型的Bean,就会抛出异常。在③处,使用@SpringBeanByName 注解从Spring容器中加载一个与当前属性名称相同的Bean。
集成Hibernate
Hibernate是一个优秀的O / R开源框架,它极大地简化了应用程序的数据访问层开发。虽然我们在使用一个优秀的O/R框架,但并不意味我们无须对数据访问层进行单元测试。单元测试仍然非常重要。它不仅可以确保Hibernate映射类的映射正确性,也可以很便捷地测试HQL查询等语句。Unitils为方便测试 Hibernate,提供了许多实用的工具类,如HibernateUnitils就是其中一个,使用assertMappingWithDatabaseConsistent()方法,就可以方便测试映射文件的正确性。
SessionFactory 配置
可以简单地在一个类、方法或者属性上加上@ HibernateSessionFactory 注解,并用Hibernate的配置文件作为参数,来加载Hibernate上下文。下面我们通过实例来介绍一下如何创建SessionFactory。
…
@HibernateSessionFactory("hibernate.cfg.xml")
public class BaseDaoTest extends UnitilsJUnit4 {
@HibernateSessionFactory
public SessionFactory sessionFactory; @Test
public void testSessionFactory(){
assertNotNull(sessionFactory);
}
}
在父类BaseDaoTest里指定了Hibernate配置文件,Hibernate应用上下文只会创建一次,然后在子类SimpleUserDaoTest里会重用这个应用程序上下文。加载Hibernate应用上下文是一个非常繁重的操作,如果重用这个Hibernate应用上下文就会大大提升测试的性能。
…
public class SimpleUserDaoTest extends BaseDaoTest {
private UserDao userDao; //① 初始化UserDao
@Before
public void init(){
userDao = new WithoutSpringUserDaoImpl();
userDao.setSessionFactory(sessionFactory); //使用父类的SessionFactory
} //② Hibernate映射测试
@Test
public void testMappingToDatabase() {
HibernateUnitils.assertMappingWithDatabaseConsistent();
} //③ 测试UserDao
@Test
public void testUserDao(){
assertNotNull(userDao);
assertNotNull(userDao.findUserByUserName("tom"));
assertEquals("tom", userDao.findUserByUserName("tom").getUserName());
}
}
…
为了更好演示如何应用Unitils测试基于Hibernate数据访问层,在这个实例中不使用Spring框架。所以在执行测试时,需要先创建相应的数据访问层实例,如实例中的userDao。其创建过程如①处所示,先手工实例化一个UserDao,然后获取父类中创建的SessionFactory,并设置到UserDao中。在②处,使用Unitils提供的工具类HibernateUnitils中的方法测试我们的Hibernate映射文件。在③处,通过JUnit的断言验证 UserDao相关方法,看是否与我们预期的结果一致。
集成Dbunit
Dbunit是一个基于JUnit扩展的数据库测试框架。它提供了大量的类,对数据库相关的操作进行了抽象和封装。Dbunit通过使用用户自定义的数据集以及相关操作使数据库处于一种可知的状态,从而使得测试自动化、可重复和相对独立。虽然不用Dbunit也可以达到这种目的,但是我们必须为此付出代价(编写大量代码、测试及维护)。既然有了这么优秀的开源框架,我们又何必再造轮子。目前其最新的版本是2.4.8。
随着Unitils的出现,将Spring、Hibernate、DbUnit等整合在一起,使得DAO层的单元测试变得非常容易。Unitils采用模块化方式来整合第三方框架,通过实现扩展模块接口org.unitils.core.Module来实现扩展功能。在Unitils中已经实现一个DbUnitModule,很好整合了DbUnit。通过这个扩展模块,就可以在Unitils中使用Dbunit强大的数据集功能,如用于准备数据的@DataSet注解、用于验证数据的@ExpectedDataSet注解。Unitils集成DbUnit流程图如图16-5所示。
16.4.5 自定义扩展模块
Unitils通过模块化的方式来组织各个功能模块,对外提供一个统一的扩展模块接口org.unitils.core.Module来实现与第三方框架的集成及自定义扩展。在Unitils中已经实现目前一些主流框架的模块扩展,如Spring、Hibernate、DbUnit、Testng等。如果这些内置的扩展模块无法满足需求,我们可以实现自己的一些扩展模块。扩展Unitils模块很简单,如代码清单16-19所示。
package sample.unitils.module;
import java.lang.reflect.Method;
import org.unitils.core.TestListener;
import org.unitils.core. Module;
//① 实现Module接口
public class CustomExtModule implements Module {
//② 实现获取测试监听的方法
public TestListener getTestListener() {
return new CustomExtListener();
} //② 新建监听模块
protected class CustomExtListener extends TestListener {
//③ 重写 TestListener里的相关方法,完成相关扩展的功能
@Override
public void afterTestMethod(Object testObject, Method testMethod,
Throwable testThrowable) {
…
} @Override
public void beforeTestMethod(Object testObject, Method testMethod) {
…
}
}
…
}
在①处新建自定义扩展模块CustomExtModule,实现Module接口。在②处新建自定义监听模块,继承TestListener。在③处重写(@Override)TestListener里的相关方法,完成相关扩展的功能。实现自定义扩展模块之后,剩下的工作就是在Unitils配置文件unitils.properties中注册这个自定义扩展的模块:
引用
unitils.modules=…,custom
unitils.module. custom.className= sample.unitils.module.CustomExtModule
单元测试工具 unitils的更多相关文章
- 主流的单元测试工具之-JAVA新特性-Annotation 写作者:组长 梁伟龙
1:什么是Annotation?Annotation,即“@xxx”(如@Before,@After,@Test(timeout=xxx),@ignore),这个单词一般是翻译成元数据,是JAVA的一 ...
- codeblocks+Mingw 下配置开源c++单元测试工具 google test
google test 是google的c++开源单元测试工具,chrome的开发团队就是使用它. Code::Blocks 12.11(MinGW 4.7.1) (Windows版)Google T ...
- PHP单元测试工具PHPUnit初体验
今天接到了个任务,需要对数字进行计算,因为涉及到整数,小数,和科学计数法等很多条件,所以人工测试非常麻烦,于是想到了PHP的单元测试工具PHPUnit,所以写个文档备查. 看了PHPUnit的文档之后 ...
- 单元测试工具之Xunit
在.NET开发中的单元测试工具之——xUnit.Net 原始出处 http://zhoufoxcn.blog.51cto.com/792419/1172320 在上一篇<在.NET开发中的单元 ...
- Java单元测试工具:JUnit4(一)(二)(三)(四)
Java单元测试工具:JUnit4(一)--概述及简单例子 Java单元测试工具:JUnit4(二)--JUnit使用详解 Java单元测试工具:JUnit4(三)--JUnit详解之运行流程及常用注 ...
- 单元测试工具 SmokeTest
.NET 程序集单元测试工具 SmokeTest Smoke Test(冒烟测试),也称Regression Test(回归测试),是对软件的安装和基本功能的测试.一般地我们使用脚本来实现Smoke ...
- Web Service单元测试工具实例介绍之SoapUI
原文 Web Service单元测试工具实例介绍之SoapUI SoapUI是当前比较简单实用的开源Web Service测试工具,提供桌面应用程序和IDE插件程序两种使用方式.能够快速构建项目和组 ...
- Java程序单元测试工具对比——Parasoft Jtest与Junit
Web应用程序开发中,面向对象的Java语言占了不少的比重.对于Java应用程序的测试方法或方式多种多样,比较典型的是程序员自己来完成程序测试中的一个部分——单元测试. 之前,慧都资讯提到单元测试是程 ...
- 一种数据与逻辑分离的Python单元测试工具
一种数据与逻辑分离的Python单元测试工具 几个概念 TestCase TestCase是一个完整的测试单元,最小的测试执行实体,就是我们常说的测试用例. TestSuite 以某种特性将测试用例组 ...
随机推荐
- How to use pthread_create && mutex?
1 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread. ...
- CentOS7.2 多个python版本共存
1.查看是否已经安装Python CentOS 7.2 默认安装了python2.7.5 因为一些命令要用它比如yum 它使用的是python2.7.5. 使用python -V命令查看一下是否安装P ...
- 通过redis协议构建脏字过滤微服务
下载 https://github.com/jonnywang/... 安装使用 mkdir -p /data/server/wordsFilter cd /data/server/wordsFilt ...
- 使用SQLAlchemy对博客文章进行分页
https://blog.csdn.net/hyman_c/article/details/54382161
- Vue packages version mismatch
开发过程中,之前做的vue项目,一段时间后拿出来重新运行,报错: 打开vue-template-compiler/index.js查看错误提示,如下: 当安装的vue版本和package.json中的 ...
- (20)Spring Boot Servlet【从零开始学Spring Boot】
Web开发使用 Controller 基本上可以完成大部分需求,但是我们还可能会用到 Servlet.Filter.Listener.Interceptor 等等. 当使用Spring-Boot时,嵌 ...
- 基于Mysql-Proxy 实现MariaDB 读写分离
一.Mysql-Proxy 简单介绍 MySQL-Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测.分析或改变它们的通信.它使用灵活,没有限制,常见的用途包 ...
- 洛谷 P1197 BZOJ 1015 [JSOI2008]星球大战 (ZOJ 3261 Connections in Galaxy War)
这两道题长得差不多,都有分裂集合的操作,都是先将所有操作离线,然后从最后一步开始倒着模拟,这样一来,分裂就变成合并,也就是从打击以后最终的零散状态,一步步合并,回到最开始所有星球都被连为一个整体的状态 ...
- hdu 3714 三分
#include<stdio.h> #define mi 1e-9 #define N 11000 struct node{ double x,y,z; }a[N]; int n; dou ...
- 转载 - C++ bitset类使用与简介
出处:http://blog.163.com/lixiangqiu_9202/blog/static/53575037201251121331412/ C++ bitset类的使用与简介 有些程序 ...