- 浏览: 712866 次
- 性别:
- 来自: 北京
-
文章分类
- 全部博客 (272)
- Struts1.x (7)
- 事务 (2)
- Hibernate (11)
- 数据库 (14)
- JavaScript&Ajax (43)
- JSP&Servlet (2)
- Flex (1)
- 其它 (9)
- Java (22)
- 框架集成 (1)
- WebService (3)
- Tomcat (3)
- 加密和安全登录 (13)
- 基于原型的JavaScript (0)
- JavaDoc和Java编码规范 (3)
- CAS (1)
- 加密 (1)
- Axis2 (10)
- Ext2.x (3)
- SSH整合 (2)
- Ext (0)
- 正则表达式 (1)
- 设计模式 (4)
- 对象序列化技术 (3)
- CVS (2)
- Struts2 (6)
- Spring 2.x (7)
- Spring Security (2)
- Java 课程 (20)
- 程序员之死 (1)
- 软件测试 (6)
- UML (5)
- NetBeans (1)
- cxf (1)
- JMS (13)
- 设计 (5)
- ibatis2.x (3)
- Oracle (1)
- WebSphere (7)
- 概要设计 (1)
- DB2 (10)
- PowerDesigner (0)
- 软件工程 (5)
- rose (1)
- EA (1)
- LDAP (7)
- Portal&Portlet (3)
- MQ (10)
- ESB (4)
- EJB (2)
- JBoss (2)
最新评论
-
typeRos:
只有配置文件,没有代码么大神
Spring实现IBMMQ的JMS消息发布/订阅模式 -
panamera:
如果ActiveMQ服务器没有启动,这个时候消息生产者使用Jm ...
Spring JMSTemplate 与 JMS 原生API比较 -
lian819:
顶1楼, 引用文件, 配置属性, 太方便了
EXTJS 同步和异步请求 -
wilhard:
说得清楚明白
<%@ include file=""%>与<jsp:include page=""/>区别 -
刘琛颖:
总结的很好。受益了
javascript 父窗口(父页面)— 子窗口 (子页面)互相调用的方法
2005 年出版《精通 JBuilder 2005》,于2007年出版《精通 Spring 2.x--企业应用开发详解》,其新作《EXT
2.x开发详解――AJAX和Web页面布局王者至尊》即将出版。
简介: Spring 2.5 TestContext 测试框架用于测试基于 Spring 的程序,TestContext 测试框架和低版本
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 等测试框架下。
在拙作《精通 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
框架结合起来,以上所有问题都将迎刃而解。
在具体使用 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() 方法执行用户登录成功后的业务逻辑:
- 登录用户添加 5 个积分(t_user.credits);
- 登录用户的最后访问时间(t_user.last_visit)和 IP(t_user.last_ip)更新为当前值;
- 在日志表中(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 编写一个简单的测试用例类,此时的目标是让这个基于 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 注解达到这个目的,请看下面的代码:
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)。下面,我们补充这项重要的检查数据正确性的工作:
@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
在数据库中访问业务方法的执行情况。
在前面,我们直接通过扩展 AbstractTransactionalJUnit4SpringContextTests 编写测试用例,在了解了编写基于
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 框架中。
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 包下找到整合的帮助类。
学习
-
Spring 系列:Spring 框架简介:优秀的 Spring 框架入门系列,了解 Spring
框架的基本概念。
-
轻量级开发的成功秘诀,第 3 部分: Spring 露出水面:介绍了在
Spring 框架的轻量级 Ioc 容器。
-
Spring Framework 和 IBM WebSphere Application
Server:Interface21 的首席执行官 Rod Johnson 和 IBM 的 WebSphere Open Source
主管 Paul Buck 讨论了 Spring Framework 通过 IBM WebSphere Application Server 认证对 Spring
和 WebSphere 产品系列的开发人员和客户有何重要意义。
-
Tiger 中的注释,第 1 部分: 向 Java
代码中添加元数据:解释了元数据如此有用的原因,向您介绍了 Java 语言中的注释,并研究了 Tiger 的内置注释。
-
Tiger 中的注释,第 2 部分:
定制注释:说明了如何创建定制注释,如何用自己的注释注解文档,并进一步定制代码。
获得产品和技术
- Springframework 网站:下载 Spring 框架。
发表评论
-
OO系统分析员之路--用例分析系列(2)--用例的类型与粒度
2011-09-14 12:03 1079在正式讨论如何获取用例之前,笔者觉得有两个问题还是先解释清楚为 ... -
JUnit入门
2011-03-08 10:46 1072一、简介 JUnit是一个开源的java单元测试框架。在1 ... -
通信软件白盒测试的三种境界
2010-07-22 20:13 1685通信软件被普遍认为是白盒测试最难实施的领域,一方面,通信软件以 ... -
性能测试兵法
2010-07-22 18:19 940~ ... -
JAVA开发过程中如何避免代码编程上带来的性能问题?
2010-07-22 17:44 1138在程序开发过程中怎么写代码才能避免性能上的问题,J ...
相关推荐
内容概要:本文详细介绍了香蕉成熟度分类的YOLO格式目标检测数据集,涵盖数据集结构、标签格式、数据集划分及其在目标检测中的应用。数据集包含18074张图像,分为训练集、验证集和测试集。标签文件采用YOLO格式,记录了每个目标物体的类别ID、中心坐标和宽高。文中还提供了Python代码示例,展示了如何读取和解析标签文件、进行数据集划分、加载和可视化数据,以及使用YOLOv8进行模型训练和推理。此外,讨论了数据增强、类别不平衡等问题的解决方案,强调了数据质量和模型优化的重要性。 适合人群:从事计算机视觉研究和技术开发的专业人士,尤其是对目标检测感兴趣的开发者。 使用场景及目标:适用于需要进行目标检测特别是香蕉成熟度分类的研究项目。主要目标是帮助研究人员更好地理解和利用YOLO格式数据集,提高模型训练效率和准确性。 其他说明:文中提供的代码片段和配置文件示例有助于读者快速上手实践,同时提醒了一些常见问题和注意事项,如数据集类别ID的连续性和样本不均衡处理等。
浙江大学第二弹:DeepSeek模型解读
内容概要:本文详细介绍了如何利用MATLAB构建齿轮-轴-轴承系统的含间隙非线性动力学模型,并对其动态特性进行了深入分析。首先,通过牛顿第二定律和修正Capone模型的雷诺方程建立了系统的非线性动力学方程。接着,展示了具体的MATLAB代码实现,包括参数设定、微分方程求解以及图像绘制。通过对不同转速下的位移-速度图像的观察,揭示了系统的混沌特性和动态响应。此外,文章还探讨了齿轮啮合的非线性刚度和轴承油膜力的影响,强调了这些因素对系统稳定性的重要作用。 适合人群:机械工程领域的研究人员和技术人员,尤其是那些对非线性动力学感兴趣的学者。 使用场景及目标:适用于研究齿轮-轴-轴承系统的动态特性,特别是用于分析系统在不同工况下的稳定性、响应速度和混沌现象。目标是通过数值模拟和理论分析相结合的方式,优化机械系统的设计。 其他说明:文中提供了详细的MATLAB代码示例,便于读者理解和实践。同时,文章还讨论了一些实用的调试技巧和注意事项,有助于提高仿真的效率和准确性。
【案例】浅谈电商运营模型及会员体系(15页 PPT)
内容概要:本文详细探讨了基于图神经网络(GNN)的Few-Shot小样本学习的实现方法及其在图像识别领域的应用。文章首先介绍了图形模型的构成,解释了如何将输入图像转化为图结构,并通过图神经网络进行信息传递和特征提取。接着,文章深入解析了图神经网络的具体结构和实现代码,包括图构建、消息传递层以及门控机制等关键技术。此外,文中还讨论了该模型的强大扩展性和适应性,如应用于半监督学习和主动学习场景,并展示了其在miniImageNet等数据集上的优异性能。最后,文章分享了一些实用技巧,如数据增强方法和优化策略,进一步提升了模型的表现。 适合人群:对机器学习特别是小样本学习感兴趣的科研人员和技术开发者。 使用场景及目标:适用于需要处理少量标注数据的任务,如快速识别新类别物体、跨域迁移学习等。目标是提高模型在小样本条件下的泛化能力和准确性。 其他说明:文章提供了详细的代码示例和实验结果,有助于读者理解和复现相关工作。同时,强调了图神经网络在捕捉数据间关系方面的独特优势,为解决小样本学习问题提供了新的思路。
# 基于Vue.js框架的商品管理系统 ## 项目简介 本项目是一个基于Vue.js框架搭建的商品管理系统,整合了商品分类、参数、列表管理,权限管理,订单管理以及数据统计等核心功能。项目采用模块化设计理念,代码结构清晰,便于后续维护与扩展。 ## 项目的主要特性和功能 1. 登录与权限管理 实现用户登录功能,验证用户信息,登录成功后存储token至客户端sessionStorage,确保项目其他接口在登录状态下可访问。 具备路由导航守卫,控制路由导航权限,防止未登录用户访问受限页面。 支持权限列表和角色列表管理,可进行角色的添加、修改、删除操作,为角色分配权限,为用户分配角色。 2. 商品管理 分类管理支持商品分类的添加、修改、删除,提供级联选择器选择父级分类。 参数管理管理商品的参数信息,支持添加、修改、删除参数,可根据分类选择展示对应参数。
《微信小程序掌上就医宝》的源码是一套基于微信平台开发的医疗健康服务系统,它集成了多种便捷功能,旨在提升患者的就医体验。该源码支持自助建档、预约挂号、门诊缴费、预交押金、报告查询、住院清单查询等业务办理,同时还提供专家出诊信息、健康宣教、就医须知及便民服务等功能。 使用该源码,患者可以通过微信公众号或小程序轻松预约医生号源,选择最合适的时间段就诊,避免长时间排队等待。此外,还支持挂号费用的在线支付(医保或自费),无需现场排队,节省时间。门诊就诊后,患者可以直接通过手机完成处方或检查检验项目的支付,无需再去收费口排队。对于在医院进行的检查及检验,患者可以通过公众号随时查询结果,不必再跑医院领取。 该源码适用于各级公立和民营医院、乡镇卫生院等医疗机构,可用于搭建互联网医院平台,实现与院内HIS、LIS、PACS系统的无缝对接。它是一套功能强大、实用性高的医疗健康服务解决方案,为患者提供了更加便捷、高效的医疗服务体验。请注意,本资源仅用于学习交流,严禁用于商业用途!
DeepSeek 提示词设计、幻觉避免与应用(50页)
内容概要:本文探讨了基于非合作博弈的居民负荷分层调度模型,旨在解决电力领域中居民用户柔性负荷资源的有效参与需求响应的问题。文中介绍了模型的构建思路,包括日前投标环节和实时调度环节的具体实现方式。日前投标环节通过非合作博弈思想构建以聚合商利润最大化为目标的博弈模型,并证明纳什均衡解的存在性。实时调度环节则以分类柔性负荷各自的用电物理特性为约束条件,以实时调度和日前投标量之间的偏差最小为目标函数。此外,还采用了双层鲸鱼算法来求解整个模型,确保在不影响用户舒适度的前提下提高聚合商的利润。仿真结果显示,该模型能够在提升电网稳定性的同时,兼顾用户舒适度和聚合商利润。 适用人群:适用于对电力调度、博弈论以及优化算法感兴趣的科研人员和技术开发者。 使用场景及目标:该模型主要用于电力系统的优化调度,特别是在需求响应管理中,帮助电网公司、负荷聚合商和居民用户实现三方共赢。具体应用场景包括电力市场竞价、居民用电负荷调控等。 其他说明:文章不仅提供了详细的理论背景介绍,还包括了具体的代码实现示例,有助于读者深入理解和实际应用。
数据说明: 该数据集包含4个不同地形类别(沙漠、森林、山脉和平原)的3196张图像,对于许多应用具有巨大的潜力。每个类别代表一个独特的生态景观,为研究人员和实践者提供了对多种地形类型的全面视角。从沙漠的干旱广阔到森林的郁郁葱葱,从山脉的崎岖地形到广阔的平原,该数据集囊括了地球表面的丰富性和多样性。 该数据集的一个重要应用是土地分类。通过利用卷积神经网络(CNN)等机器学习技术,研究人员可以自动训练模型根据航空图像分类地形类型。这种能力对土地管理、环境监测和城市规划有着深远的影响。准确的分类使利益攸关方能够就资源分配、生境保护和可持续发展倡议作出知情的决定。 地理分析是另一个关键领域,该数据集在其中具有实用价值。地理学家和研究人员可以利用该数据集研究不同地形类型的土地覆盖变化、生态系统动态和地理模式。通过分析每个类别中特征的空间分布,可以深入了解栖息地碎片化、生物多样性热点和土地利用趋势。此类分析有助于了解地球的地貌,并为保护工作和政策制定提供信息。
《图书馆门户小程序源码及手册简介》 本资源是一套极具价值的学习资源——图书馆门户小程序源码及使用手册。该小程序功能丰富且全面,前后端完整代码一应俱全。它涵盖了图书馆的多个重要功能模块,如“本馆动态”,能让用户及时了解图书馆的最新资讯;“新书来了”方便读者知晓新书上架情况;“书籍榜单”助力用户发现热门书籍;“服务指南”为读者提供各类服务的详细指引;“进馆预约”和“活动讲座预约”则满足了读者对图书馆空间及文化活动的参与需求。通过研读这份源码和使用手册,学习者可以深入了解图书馆小程序的开发逻辑、架构设计以及功能实现方式,无论是对于想要提升编程能力的开发者,还是希望探索图书馆数字化建设的相关人员,都具有重要的学习和参考价值,有助于拓宽技术视野,提升实践能力,为相关项目的开发与优化提供有力支持。
内容概要:本文详细介绍了利用灰狼算法(GWO)实现光伏系统的最大功率点跟踪(MPPT)的方法。针对光伏阵列在部分遮阴条件下的多峰特性,传统MPPT算法易陷入局部最优的问题,作者提出了一种基于灰狼算法的解决方案。文中展示了如何在MATLAB中编写灰狼算法的核心逻辑,并将其集成到Simulink环境中构建闭环控制系统。具体措施包括自适应调整占空比范围、引入电压补偿项以及动态改变收敛因子等,确保算法在光照突变情况下仍能迅速找到全局最优解。实验结果显示,相比传统方法,灰狼算法不仅提高了响应速度,还增强了稳定性。 适合人群:从事光伏系统研究与开发的技术人员,尤其是关注MPPT算法优化的研究者。 使用场景及目标:适用于需要提高光伏系统在复杂环境下的发电效率的应用场合,旨在克服现有MPPT算法在处理部分遮阴情况时存在的局限性。 其他说明:文中提供了详细的代码片段和实验数据,帮助读者更好地理解和复现研究成果。此外,还讨论了一些实际应用中的注意事项和技术细节,如狼群数量的选择、采样周期的设定等。
《色素性皮肤病自动识别系统资源简介》 本资源是一套完整的色素性皮肤病自动识别系统,包含源码与数据集。该系统运用了先进的集成学习、迁移学习以及GAN等前沿技术,实现了对色素性皮肤病的精准自动识别,且具备七分类功能。 在服务端,通过这些先进技术构建起强大的识别模型,能够准确判断不同类别的色素性皮肤病。而客户端则采用微信小程序和网站两种形式进行呈现,方便用户使用。其中,网站的开发运用了SSM框架和Springboot技术,确保了系统的高效运行和稳定交互。 此资源对于学习和研究计算机视觉、深度学习在医学图像处理领域的应用具有重要价值。无论是从事相关科研工作的专业人员,还是对该领域感兴趣的学习者,都能从中获取丰富的知识和实践经验,深入了解如何利用先进技术解决实际医学问题,推动医疗领域的智能化发展。总之,这是一份极具学习价值的宝贵资源。
# 基于Arduino的温度控制系统 ## 项目简介 这是一个基于Arduino的温度控制系统项目,可实现自动温度控制功能,适用于家庭、实验室、工业等各种需要精确温度控制的场景。 ## 项目的主要特性和功能 1. 实时温度监控能实时读取环境温度。 2. 自动温度控制依据设定的温度阈值,自动调整加热或冷却设备,保持环境在设定温度范围内。 3. 温度阈值设置用户可自定义温度阈值。 4. 简单易用通过Arduino编程实现,代码易理解和修改。 ## 安装使用步骤 1. 准备工作准备好Arduino开发板、温度传感器、加热冷却设备及相应连接线。 2. 硬件连接把温度传感器、加热冷却设备连接到Arduino开发板。 3. 上传代码将提供的Arduino代码上传至开发板。 4. 设置温度阈值通过代码或Arduino IDE的串口监视器设置期望的温度阈值。 5. 测试与调试接通电源,观察系统能否根据环境温度自动调整加热或冷却设备。
数据说明: 该数据集可以做一个简单的图像分类器来识别卡通人物。它包含了超过4600张受大众喜欢的迪士尼角色图片。分别为:奥拉夫,唐老鸭,米老鼠,庞巴,小黄人,维尼熊,分为训练和测试集。
内容概要:费曼学习法强调学习的本质在于有效联系真实世界并学以致用,其核心理念是以输出促输入,通过向他人传授知识来加深自身的理解和掌握。此方法鼓励学习者从远见、穿透力、智慧三个维度提升自我,即预测未来趋势、洞悉知识本质、浓缩重演知识。具体步骤包括:确立目标,理解对象,以教代学,回顾反思,简化吸收。其中,以教代学是费曼学习法的重要环节,主张通过模拟传授场景,用简洁易懂的语言讲解知识点,确保精准无歧义,并加入个人见解。同时,在整个学习过程中,应注重系统化思考,如水平思考、发散思考、收敛思考等,让思考可以量化,最终实现知识的内化,形成自己的知识体系,解决实际问题。 适合人群:所有希望提高学习效率、深化理解、构建个人知识体系的学习者,尤其是那些渴望在某一领域成为专家的人士。 使用场景及目标:①帮助学习者明确学习目标,通过SMART原则制定具体可行的学习计划;②引导学习者系统化地收集、整理、归纳资料,建立逻辑严谨的知识框架;③通过模拟传授场景,让学习者在输出过程中检验和巩固所学知识,提高知识留存率;④促进学习者进行深度反思,修正理解偏差,回归知识本质。 阅读建议:费曼学习法不仅是一种学习技巧,更是一种思维方式的转变。在学习过程中,要不断尝试将所学知识讲给别人听,接受反馈,反复打磨,直至能够用最简单的语言解释复杂的概念。同时,保持开放心态,积极吸纳不同意见,持续优化自己的知识体系。
内容概要:本文介绍了“捉妖主升浪指标”的具体实现代码及其应用逻辑。该指标主要用于股票市场技术分析,通过一系列复杂的数学运算和条件判断,识别股票价格走势中的关键节点。核心公式包括平台突破、主力筹码、RSI等技术指标的计算,以及多个条件组合来判断不同类型的“捉妖”信号,如突破捉妖、拉升捉妖、逼空捉妖、超跌捉妖等。每个信号都有特定的颜色标识,并在图表上显示相应的提示信息。 适合人群:对股票交易和技术分析有一定了解的投资者,尤其是希望借助技术指标提高选股效率的专业人士或资深股民。 使用场景及目标:①用于股票市场的技术分析,帮助投资者识别潜在的强势股;②结合其他分析工具,为买卖决策提供参考依据;③通过捕捉短期爆发性上涨机会,优化投资组合收益。 阅读建议:由于该指标涉及较多专业术语和技术细节,建议读者先熟悉常用的技术分析方法,再深入研究此指标的具体实现逻辑。同时,在实际操作中应结合市场情况灵活运用,避免机械套用。
# 基于FreeRTOS的EDF调度系统 ## 项目简介 本项目旨在基于FreeRTOS设计一个Earliest Deadline First (EDF) 调度器,系统运行于NXP LCP2129微控制器。EDF是一种采用动态优先级预占式调度策略的算法,任务优先级在执行过程中可改变,高优先级任务请求会中断低优先级任务处理。 ## 项目的主要特性和功能 实现动态优先级调度,能根据任务截止时间动态调整优先级。 采用预占式调度策略,高优先级任务可中断低优先级任务。 ## 安装使用步骤 1. 已下载本项目的源码文件。 2. 使用Keil uVision5打开项目进行模拟运行。 ## 版本历史
基于Javaweb仓库管理系统项目源码
可以把安装在电脑上的Windows 10企业版、教育版、专业版系统改装成Windows 10家庭版操作系统。