使用
Spring 2.5 TestContext
测试框架
陈
雄华
(
quickselect@163.com
),
技术总监
,
宝宝淘网络科技有限公司
简介:
Spring 2.5 TestContext
测试框架用于测试基于
Spring
的程序,
T
estContext
测试
框架和低版本
Spring
测试框架没有任何关系,是一个全新的基于注解的测试框架,为
Spring
推荐使用该测试框架。
概述
Spring 2.5
相比于
Spring 2.0
所新增的最重要的功能可以归结为以下
3
点:
基于注解的
IoC
功能;
基于注解驱动的
Spring MVC
功能;
基于注解的
TestContext
测试框架。
Spring
推荐开发者使用新的基于注解的
TestContext
测试框架,
本文我们将对此进行详细
的讲述。
低版本的
Spring
所提供的
Spring
测试框架构在
JUnit 3.8
基础上扩展而来,
它提供了若
干个测试基类。
而
Spring 2.5
所新增的基于注解的
TestContext
测试框架和低版本的测试
框架没有任何关系。它采用全新的注解技术可以让
POJO
成为
Spring
的测试用例,除了
拥有旧测试框架所有功能外,
TestContext
还添加了一些新的功能,
TestContext
可以运行
在
JUnit 3.8
、
JUnit 4.4
、
TestNG
等测试框架下。
直接使用
JUnit
测试
Spring
程序存在的不足
在拙作
《精通
Spring 2.x
—
企业应用开发详解》
一书中,
笔者曾经指出如果直接使用
JUnit
测试基于
Spring
的程序,将存在以下
4
点明显的不足:
导致
Spring
容器多次初始化问题:
根据
JUnit
测试用例的调用流程,
每执行一个
测试方法都会重新创建一个测试用例实例并调用其
setUp()
方法。
由于在一般情况
下,我们都在
setUp()
方法中初始化
Spring
容器,这意味着测试用例中有多少个
测试方法,
Spring
容器就会被重复初始化多少次。
需要使用硬编码方式手工获取
Bean
:
在测试用例中,我们需要通过
ApplicationContext.getBean()
的方法从
Spirng
容器中获取需要测试的目标
Bean
,并且还要进行造型操作。
数据库现场容易遭受破坏:
测试方法可能会对数据库记录进行更改操作,破坏数据
库现场。
虽然是针对开发数据库进行测试工作的,
但如果数据操作的影响是持久的,
将会形成积累效应并影响到测试用例的再次执行。举个例子,假设在某个测试方法
中往数据库插入一条
ID
为
1
的
t_user
记录,第一次运行不会有问题,第二次运
行时,就会因为主键冲突而导致测试用例执行失败。所以测试用例应该既能够完成
测试固件业务功能正确性的检查,又能够容易地在测试完成后恢复现场,做到踏雪
无迹、雁过无痕。
不容易在同一事务下访问数据库以检验业务操作的正确性:
当测试固件操作数据库
时,为了检测数据操作的正确性,需要通过一种方便途径在测试方法相同的事务环
境下访问数据库,以检查测试固件数据操作的执行效果。如果直接使用
JUnit
进行
测试,我们很难完成这项操作。
Spring
测试框架是专门为测试基于
Spring
框架应用程序而设计的,它能够让测试用例非
常方便地和
Spring
框架结合起来,以上所有问题都将迎刃而解。
一个需要测试的
Spring
服务类
在具体使用
TextContext
测试框架之前,
我们先来认识一下需要测试的
UserService
服务
类。
UserService
服务类中拥有一个处理用户登录的服务方法,其代码如下所示:
清单
1. 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;
public class UserService{
private UserDao userDao;
private LoginLogDao loginLogDao;
public void handleUserLogin(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);
}
//
省略
get/setter
方法
}
UserService
需要调用
DAO
层的
UserDao
和
LoginLogDao
以及
User
和
LoginLog
这两个
PO
完成业务逻辑,
User
和
LoginLog
分别对应
t_user
和
t_login_log
这两张数
据库表。
在用户登录成功后调用
UserService
中的
handleUserLogin()
方法执行用户登录成功后
的业务逻辑:
1.
登录用户添加
5
个积分(
t_user.credits
);
2.
登录用户的最后访问时间
(
t_user.last_visit
)
和
IP
(
t_user.last_ip
)
更新为当前值;
3.
在日志表中(
t_login_log
)中为用户添加一条登录日志。
这是一个需要访问数据库并存在数据更改操作的业务方法,
它工作在事务环境下。
下面是装
配该服务类
Bean
的
Spring
配置文件:
清单
2. applicationContext.xml
:
Spring
配置文件,放在类路径下
<?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:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--
配置数据源
-->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost/sampledb"
p:username="root"
p:password="1234"/>
<!--
配置
Jdbc
模板
-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"/>
<!--
配置
dao -->
<bean id="loginLogDao"class="com.baobaotao.dao.LoginLogDao"
p:jdbcTemplate-ref="jdbcTemplate"/>
<bean id="userDao" class="com.baobaotao.dao.UserDao"
p:jdbcTemplate-ref="jdbcTemplate"/>
<!--
事务管理器
-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
<bean id="userService" class="com.baobaotao.service.UserService"
p:userDao-ref="userDao" p:loginLogDao-ref="loginLogDao"/>
<!--
使用
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>
UserService
所关联的
DAO
类和
PO
类都比较简单,请参看本文附件的程序代码。在着
手测试
UserSerivce
之前,
需要将创建数据库表,
你可以在附件的
schema
目录下找到相
应的
SQL
脚本文件。
编写
UserService
的测试用例
下面我们为
UserService
编写一个简单的测试用例类,此时的目标是让这个基于
TestContext
测试框架的测试类运行起来,我们将在后面逐步完善这个测试用例。
清单
3.TestUserService.java:
基于注解的测试用例
package com.baobaotao.service;
import org.springframework.test.context.junit4.
AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.junit.Test;
import com.baobaotao.domain.User;
import java.util.Date;
@ContextConfiguration //
①
public class TestUserService extends
AbstractTransactionalJUnit4SpringContextTests {
@Autowired //
②
private UserService userService;
@Test //
③
public void handleUserLogin(){
User user = new User();
user.setUserId(1);
user.setLastIp("127.0.0.1");
Date now = new Date();
user.setLastVisit(now.getTime());
userService.handleUserLogin(user);
}
}
这里,我们让
TestUserService
直接继承于
Spring
所提供的
AbstractTransactionalJUnit4SpringContextTests
的抽象测试类,
稍后本文将对这个抽象测
试类进行剖析,这里你仅须知道该抽象测试类的作用是让
TestContext
测试框架可以在
JUnit 4.4
测试框架基础上运行起来就可以了。
在
①
处,标注了一个类级的
@ContextConfiguration
注解,这里
Spring
将按
TestContext
契约查找
classpath:/com/baobaotao/service/TestUserService-context.xml
的
Spring
配置文件,并使用该配置文件启动
Spring
容器。
@ContextConfiguration
注解
有以下两个常用的属性:
locations
:可以通过该属性手工指定
Spring
配置文件所在的位置,可以指定一个
或多个
Spring
配置文件。如下所示:
@ContextConfiguration(locations={“xx/yy/beans1.xml”,”
xx/yy/beans2.xml”})
inheritLocations
:是否要继承父测试用例类中的
Spring
配置文件,默认为
true
。
如下面的例子:
@ContextConfiguration(locations={"base-context.xml"})
public class BaseTest {
// ...
}
@ContextConfiguration(locations={"extended-context.xml"})
public class ExtendedTest extends BaseTest {
// ...
}
如果
inheritLocations
设置为
false
,则
ExtendedTest
仅会使用
extended-context.xml
配置文件,否则将使用
base-context.xml
和
extended-context.xml
这两个配置文件。
②
处的
@Autowired
注解让
Spring
容器自动注入
UserService
类型的
Bean
。而在
③
处标注的
@Test
注解则让
handleUserLogin()
方法成为一个
JUnit
4.4
标准的测试方法,
@Test
是
JUnit 4.4
所定义的注解。
在运行
TestUserService
测试类之前,让我们先看一下
TestUserService-context.xml
配
置文件的内容:
清单
4.TestUserService
所引用的
Spring
配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--
①
引入清单
1
定义的
Spring
配置文件
-->
<import resource="classpath:/applicationContext.xml"/>
</beans>
在
①
处引入了清单
1
中定义的
Spring
配置文件,这样我们就可以将其中定义的
UserService Bean
作为测试固件注入到
TestUserService
中了。
在你的
IDE
中(
Eclipse
、
JBuilder
、
Idea
等),将
JUnit 4.4
类包引入到项目工程中后,
在
TestUserService
类中点击右键运行该测试类,
将发现
TestUserService
已经可以成功
运行了,如
图
1
所示:
图
1.
在
Eclipse 6.0
中运行
TestUserService
TestUserService
可以正确运行,说明其
userService
这个测试固件已经享受了
Spring
自动注入的功能。在运行该测试用例后,到数据库中查看
t_user
表和
t_login_log
表,你
会发现表数据和测试前是一样的!
这说明虽然我们在清单
3
的
handleUserLogin()
测试方
法中执行了
userService.handleUserLogin(user)
的操作,
但它并没有对数据库现场造成破
坏:这是因为
Spring
的在测试方法返回前进行了事务回滚操作。
虽然
TestUserService.handleUserLogin()
测试方法已经可以成功运行,
但是它在测试功能
上是不完善的,读者朋友可以已经发现了它存在以下两个问题:
我们仅仅执行了
UserService#handleUserLogin(user)
方法,但验证该方法执行结
果的正确性。
在测试方法中直接使用
ID
为
1
的
User
对象进行测试,这相当于要求在数据库
t_user
表必须已经存在
ID
为
1
的记录,
如果
t_user
中不存在这条记录,
将导致
测试方法执行失败。
准备测试数据并检测运行结果
在这节里,
我们将着手解决上面所提出的两个问题,
在测试用例中准备测试数据并到数据库
中检测业务执行结果的正确性。
准备测试数据
相比于在测试方法中直接访问预定的数据记录,
在测试方法执行前通过程序准备一些测试数
据,
然后在此基础上运行测试方法是比较好的策略,
因为后者不需要对数据库的状态做假设。
在
TestContext
中,你可以通过使用
JUnit 4.4
的
@Before
注解达到这个目的,请看下
面的代码:
清单
5.
为测试方法准备数据
package com.baobaotao.service;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.
AbstractTransactionalJUnit4SpringContextTests;
import com.baobaotao.dao.UserDao;
import com.baobaotao.domain.User;
@ContextConfiguration
public class TestUserService
extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired
private UserService userService;
@Autowired
private UserDao userDao;
private int userId;
@Before //
①
准备测试数据
public void prepareTestData() {
final String sql = "insert into t_user(user_name,password)
values('tom','1234')";
simpleJdbcTemplate.update(sql);
KeyHolder keyHolder = new GeneratedKeyHolder();
simpleJdbcTemplate.getJdbcOperations().update(
new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql);
return ps;
}
}, keyHolder);
userId = keyHolder.getKey().intValue();//
①-
1
记录测试数据的
id
}
@Test
public void handleUserLogin(){
User user = userDao.getUserById(userId); //
②
获取测试数据
user.setLastIp("127.0.0.1");
Date now = new Date();
user.setLastVisit(now.getTime());
userService.handleUserLogin(user);
}
}
JUnit 4.4
允许通过注解指定某些方法在测试方法执行前后进行调用,即是
@Before
和
@After
注解。在
Spring TestContext
中,标注
@Before
和
@After
的方法会在测试用
例中每个测试方法运行前后执行,
并和测试方法运行于同一个事务中。
在
清单
5
中
①
处,
我们给
prepareTestData()
标注上了
@Before
注解,在该方法中准备一些测试数据,以
供
TestUserService
中所有测试方法使用
(这里仅有一个
handleUserLogin()
测试方法)
。
由于测试方法运行后,整个事务会被回滚,在
prepareTestData()
中插入的测试数据也不
会持久化到数据库中,因此我们无须手工删除这条记录。
标注
@Before
或
@After
注解的方法和测试方法运行在同一个事务中,但有时我们希望
在测试方法的事务开始之前或完成之后执行某些方法以便获取数据库现场的一些情况。
这时,
可以使用
Spring TestContext
的
@BeforeTransaction
和
@AfterTransaction
注解来达
到目录(这两个注解位于
org.springframework.test.context.transaction
包中)。
虽然大多数业务方法都会访问数据库,
但也并非所有需要测试的业务方法都需要和数据库打
交道。而在默认情况下,继承于
AbstractTransactionalJUnit4SpringContextTests
测试用
例的所有测试方法都将工作于事务环境下,你可以显式地通过
@NotTransactional
注解,
让测试方法不工作于事务环境下。
prepareTestData()
方法中使用到了
simpleJdbcTemplate
对象访问操作数据库,
该对象在
AbstractTransactionalJUnit4SpringContextTests
抽象类中定义,
只要
Spring
容器有配置
数据源,
simpleJdbcTemplate
就会被自动创建。同时该抽象类中还拥有一个
Spring
容器
引用:
applicationContext
,你可以借助该成员变量访问
Spring
容器,执行获取
Bean
,发
布事件等操作。
此外,
AbstractTransactionalJUnit4SpringContextTests
还提供了若干个访问数据库的便捷
方法,说明如下:
protected int countRowsInTable(String tableName)
:计算数据表的记录数。
protected int deleteFromTables(String... names)
:删除表中的记录,可以指定多张
表。
protected void executeSqlScript(String sqlResourcePath, boolean
continueOnError)
:
执行
SQL
脚本文件,
在脚本文件中,
其格式必须一个
SQL
语
句一行。
在测试方法
handleUserLogin()
的
②
处,我们通过
userDao
获取
prepareTestData()
添加的测试数据,
测试方法在测试数据的基础上执行业务逻辑。
使用这种测试方式后,
在任
何情况下运行
TestUserService
都不会发生业务逻辑之外的问题。
检验业务逻辑的正确性
到目前为此,
TestUserService
的
handleUserLogin()
测试方法仅是简单地执行
UserService#handleUserLogin()
业务方法,
但并没有在业务方法执行后检查执行结果的正
确性,
因此这个测试是不到位的。
也就是说,
我们必须访问数据库以检查业务方法对数据更
改是否成功:这包括积分
(credits)
、最后登录时间
(last_visit)
、最后登录
IP(last_ip)
以及登
录日志表中的登录日志记录
(t_login_log)
。下面,我们补充这项重要的检查数据正确性的工
作:
清单
5.
检验业务方法执行结果的正确性
@Test
public void handleUserLogin(){
User user = userDao.getUserById(userId);
user.setLastIp("127.0.0.1");
Date now = new Date();
user.setLastVisit(now.getTime());
userService.handleUserLogin(user);
//------------------
以下为业务执行结果检查的代码
---------------------
User newUser = userDao.getUserById(userId);
Assert.assertEquals(5, newUser.getCredits()); //
①检测积分
//
①检测最后登录时间和
IP
Assert.assertEquals(now.getTime(), newUser.getLastVisit());
Assert.assertEquals("127.0.0.1",newUser.getLastIp());
//
③检测登录记录
String sql = "select count(1) from t_login_log where user_id=? "+
“ and login_datetime=? and ip=
?";
int logCount =simpleJdbcTemplate.queryForInt(sql, user.getUserId(),
user.getLastVisit(),user.getLastIp());
Assert.assertEquals(1, logCount);
}
在业务方法执行后,
我们查询数据库中相应记录以检查是否和期望的效果一致,
如
①
和
②
所示。在
③
处,我们使用
SimpleJdbcTemplate
查询
t_login_log
,以检查该表中是否已
经添加了一条用户登录日志。
注意:
由于我们的
DAO
层采用
Spring JDBC
框架,
它没有采用服务层缓存技术,
所以可
以使用
DAO
类返回数据库中的数据。
如果采用
Hibernate
等
ORM
框架,
由于它们采用
了服务层缓存的技术,为了获取数据库中的相应数据,需要在业务方法执行后调用
HibernateTemplate.flush()
方法,将缓存中的对象同步到数据库中,这时才可以通过
SimpleJdbcTemplate
在数据库中访问业务方法的执行情况。
Spring TestContext
测试框架体系结构
在前面,我们直接通过扩展
AbstractTransactionalJUnit4SpringContextTests
编写测试用
例,
在了解了编写基于
TestContext
测试框架的测试用例后,现在是了解
TestContext
测
试框架本身的时候了。
TestContext
核心类、支持类以及注解类
TestContext
测试框架的核心由
org.springframework.test.context
包中三个类组成,分别
是
TestContext
和
TestContextManager
类以及
TestExecutionListener
接口。其类图如
下
图
2
所示:
图
2. Spring TestContext
测试框架核心类
TestContext
:它封装了运行测试用例的上下文;
TestContextManager
:它是进入
Spring TestContext
框架的程序主入口,它管理
着一个
TestContext
实例,并在适合的执行点上向所有注册在
TestContextManager
中的
TestExecutionListener
监听器发布事件:比如测试用
例实例的准备,测试方法执行前后方法的调用等。
TestExecutionListener
:该接口负责响应
TestContextManager
发布的事件。
Spring TestContext
允许在测试用例类中通过
@TestExecutionListeners
注解向
TestContextManager
注册多个监听器,如下所示:
@TestExecutionListeners( {
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class })
public class TestXxxService{
…
}
Spring
提供了几个
TestExecutionListener
接口实现类,分别说明如下:
DependencyInjectionTestExecutionListener
:该监听器提供了自动注入的功能,它
负责解析测试用例中
@Autowried
注解并完成自动注入;
DirtiesContextTestExecutionListener
:一般情况下测试方法并不会对
Spring
容器
上下文造成破坏(改变
Bean
的配置信息等),如果某个测试方法确实会破坏
Spring
容器上下文,你可以显式地为该测试方法添加
@DirtiesContext
注解,以
便
Spring TestContext
在测试该方法后刷新
Spring
容器的上下文,而
DirtiesContextTestExecutionListener
监听器的工作就是解析
@DirtiesContext
注
解;
TransactionalTestExecutionListener
:它负责解析
@Transaction
、
@NotTransactional
以及
@Rollback
等事务注解的注解。
@Transaction
注解让
测试方法工作于事务环境中,不过在测试方法返回前事务会被回滚。你可以使用
@Rollback(false)
让测试方法返回前提交事务。而
@NotTransactional
注解则让
测试方法不工作于事务环境中。此外,你还可以使用类或方法级别的
@TransactionConfiguration
注解改变事务管理策略,如下所示:
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
@Transactional
public class TestUserService {
…
}
我们知道在
JUnit 4.4
中可以通过
@RunWith
注解指定测试用例的运行器,
Spring
TestContext
框架提供了扩展于
org.junit.internal.runners.JUnit4ClassRunner
的
SpringJUnit4ClassRunner
运行器,它负责总装
Spring TestContext
测试框架并将其统一
到
JUnit 4.4
框架中。
TestContext
所提供的抽象测试用例
Spring TestContext
为基于
JUnit 4.4
测试框架提供了两个抽象测试用例类,分别是
AbstractJUnit4SpringContextTests
和
AbstractTransactionalJUnit4SpringContextTests
,
而后者扩展于前者。让我们来看一下这两个抽象测试用例类的骨架代码:
@RunWith(SpringJUnit4ClassRunner.class) //
①
指定测试用例运行器
@TestExecutionListeners( //
②
注册了两个
TestExecutionListener
监听器
{ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class })
public class AbstractJUnit4SpringContextTests implements ApplicationContextAware
{
…
}
①
处将
SpringJUnit4ClassRunner
指定为测试用例运行器,
它负责无缝地将
TestContext
测试框架移花接木到
JUnit 4.4
测试框架中,它是
Spring TestContext
可以运行起来的根
本所在。②
处通过
@TestExecutionListeners
注解向测试用例类中注册了两个
TestExecutionListener
监听器,这两个监听器分别负责对
@Autowired
和
@DirtiesContext
注解进行处理,
为测试用例提供自动注入和重新刷新
Spring
容器上下文
的功能。
AbstractTransactionalJUnit4SpringContextTests
扩展于
AbstractJUnit4SpringContextTests
,提供了事务管理的支持,其骨架代码如下所示:
//
①
注册测试用例事务管理的监听器
@TestExecutionListeners( { TransactionalTestExecutionListener.class })
@Transactional //
②
使测试用例的所有方法都将工作于事务环境下
public class AbstractTransactionalJUnit4SpringContextTests
extends AbstractJUnit4SpringContextTests {
…
}
在
①
处,
AbstractTransactionalJUnit4SpringContextTests
向测试用例类中注册了
TransactionalTestExecutionListener
监听器,这样测试用例中的
@Transaction
、
@NotTransaction
以及
@Rollback
等注解就可以正确地工作起来了。注意,你不需要在
Spring
配置文件通过
<tx:annotation-driven />
和
<context:annotation-config/>
为测试用
例类启用注解事务驱动和注解自动注入,这个工作完全于
TestContext
自身来解决(通过
注册
DependencyInjectionTestExecutionListener
和
TransactionalTestExecutionListener
监听器),毕竟测试用例类没有注册到
Spring
容器
中,没有成为
Spring
的
Bean
。
小结
我们通过对一个典型的涉及数据库访问操作的
UserService
服务类的测试,讲述了使用
Spring 2.5 TestContext
测试框架进行集成测试的各项问题,这包括测试固件的自动注入、
事务自动回滚、通过
SimpleJdbcTemplate
直接访问数据库以及测试数据准备等问题。
在通过一个实际例子的学习后,我们对如何使用
TestContext
测试框架有了一个具体的认
识,在此基础上我们对
Spring TestContext
测试框架体系结构进行了分析,然后剖析了
Spring
为
TestContext
嫁接到
JUnit 4.4
测试框架上所提供的两个抽象测试用例类。
Spring
的
TestContext
测试框架不但可以整合到
JUnit 4.4
测试框架上,
而且还可以整合
到
JUnit 3.8
以及
TestNG
等测试框架上。
目前已经提供了对
JUnit 3.8
以及
TestNG
的
支持,你可以分别在
org.springframework.test.context.junit38
和
org.springframework.test.context.testng
包下找到整合的帮助类。