这里将用到以下几个包:
引用 aopalliance-1.0.jar commons-collections.jar commons-dbcp.jar commons-logging-1.1.1.jar commons-pool.jar junit-4.4.jar jstl.jar log4j-1.2.15.jar mysql-connector-java-5.1.6-bin.jar spring-aop-2.5.6.jar spring-beans-2.5.6.jar spring-context-2.5.6.jar spring-context-support-2.5.6.jar spring-core-2.5.6.jar spring-jdbc-2.5.6.jar spring-tx-2.5.6.jar spring-test-2.5.6.jar spring-web-2.5.6.jar spring-webmvc-2.5.6.jar standard.jar主要增加了spring-test-2.5.6.jar和junit-4.4.jar两个用于测试的包! 这里尤其要说明一下,由于我们使用注解方式自然要用到JUnit-4.X系列,而Sring-Test对于JUnit有个累人的要求,JUnit的版本必须是4.4,不支持高版本(如4.5、4.7等)。否则,会产生java.lang.ClassNotFoundException: org.junit.Assume$AssumptionViolatedException异常。 先来一个能够自动回滚的用于测试的父类——AbstractTestCase AbstractTestCase.java
Java代码 /** * 2009-12-16 */ package org.zlex.spring; import org.junit.runner.RunWith; import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; /** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @version 1.0 * @since 1.0 */ @ContextConfiguration(locations = "classpath:applicationContext.xml") @RunWith(SpringJUnit4ClassRunner.class) @Transactional @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) public abstract class AbstractTestCase extends AbstractTransactionalDataSourceSpringContextTests { } /** * 2009-12-16 */ package org.zlex.spring; import org.junit.runner.RunWith; import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; /** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @version 1.0 * @since 1.0 */ @ContextConfiguration(locations = "classpath:applicationContext.xml") @RunWith(SpringJUnit4ClassRunner.class) @Transactional @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) public abstract class AbstractTestCase extends AbstractTransactionalDataSourceSpringContextTests { }让每一个测试类都写一堆配置忒麻烦! 索性来个老爹替子子孙孙都完成基础工作! 逐行分析: @ContextConfiguration(locations = "classpath:applicationContext.xml")导入配置文件。这时候,我们可以看出之前使用applicationContext.xml文件作为系统总控文件的好处! 当然,Spring-Test的这个配置只认classpath,很无奈,我必须拷贝这些文件到根目录! @RunWith(SpringJUnit4ClassRunner.class)SpringJUnit支持,由此引入Spring-Test框架支持! @Transactional这个非常关键,如果不加入这个注解配置,事务控制就会完全失效! @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)这里的事务关联到配置文件中的事务控制器(transactionManager = "transactionManager"),同时指定自动回滚(defaultRollback = true)。这样做操作的数据才不会污染数据库! AbstractTransactionalDataSourceSpringContextTests要想构建这一系列的无污染纯绿色事务测试框架就必须找到这个基类! 给出一个整体结构图: test子目录下的文件将编译到classpath下,这其实还同时是个maven测试项目!拷一堆配置文件的确有些不方便! AbstractTestCase.java用于抽象测试类控制。 AccountDaoTest.java用于AccountDao测试。 DaoAllTests.java用于Dao层的整体测试。 来看看AccountDaoTest AccountDaoTest.java
Java代码 /** * 2009-12-16 */ package org.zlex.spring; import java.util.Date; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.zlex.spring.dao.AccountDao; import org.zlex.spring.domain.Account; /** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @version 1.0 * @since 1.0 */ public class AccountDaoTest extends AbstractTestCase { @Autowired private AccountDao accountDao; @Test public void test() { Account ac = new Account(); ac.setBirthday(new Date()); ac.setUsername("SPRING"); ac.setPassword("SNOWOLF"); ac.setEmail("spring@zlex.org"); // 创建用户 accountDao.create(ac); // 检索 Account account = accountDao.read("SPRING"); // 校验 assertNotNull(account); } } /** * 2009-12-16 */ package org.zlex.spring; import java.util.Date; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.zlex.spring.dao.AccountDao; import org.zlex.spring.domain.Account; /** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @version 1.0 * @since 1.0 */ public class AccountDaoTest extends AbstractTestCase { @Autowired private AccountDao accountDao; @Test public void test() { Account ac = new Account(); ac.setBirthday(new Date()); ac.setUsername("SPRING"); ac.setPassword("SNOWOLF"); ac.setEmail("spring@zlex.org"); // 创建用户 accountDao.create(ac); // 检索 Account account = accountDao.read("SPRING"); // 校验 assertNotNull(account); } }只要记得使用注解@Test标识方法即可! 这里插入了一条数据,之后进行检索。如果数据存在则认为测试成功! 当然,这时候你要看看数据库是不是真的插入了一条数据! 执行这个方法,同时监控数据库,观察日志!最有效的办法是在执行检索方法时加入断点,同时监控数据库记录,你会发现此时数据库无此数据录入! 实际上这是一个未提交的事务! 完成操作,看看这时的日志: 数据库其实已经进行了回滚! 再看看DaoAllTests DaoAllTests.java
Java代码 /** * 2009-12-17 */ package org.zlex.spring; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @version 1.0 * @since 1.0 */ @RunWith(Suite.class) @SuiteClasses( { AccountDaoTest.class, AccountDaoTest.class }) public class DaoAllTests { } /** * 2009-12-17 */ package org.zlex.spring; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; /** * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> * @version 1.0 * @since 1.0 */ @RunWith(Suite.class) @SuiteClasses( { AccountDaoTest.class, AccountDaoTest.class }) public class DaoAllTests { }逐行说明: @RunWith(Suite.class)集合测试 @SuiteClasses( { AccountDaoTest.class })集合,包括AccountDaoTest类,多个测试类可使用逗号分隔! 这个测试类可用于Dao层集合测试,与Spring无关!