Downloads By http://down.liehuo.net
http://www.elecfans.com 电子发烧友 http://bbs.elecfans.com 电子技术论坛
protected void tearDown() throws Exception {
user = null; mgr = null;
}
// add testXXX methods here
public static void main(String[] args) {
junit.textui.TestRunner.run(UserDAOTest.class);
}
在setup方法中,使用ClassPathXmlApplicationContext把applicationContext.xml载入变量ApplicationContext中。载入ApplictionContext有几种途径,从classpath中,文件系统,或web 应用内。这些方法将在第三章( The BeanFactory and How It Works.)中描述。
2.输入第一个测试方法的代码,来验证Manager成功完成添加或是删除User对象。public void testAddAndRemoveUser() throws Exception { user = new User();
user.setFirstName(\Easter\); user.setLastName(\Bunny\); user = mgr.saveUser(user); assertTrue(user.getId() != null); if (log.isDebugEnabled()) {
log.debug(\removing user...\);
}
String userId = user.getId().toString(); mgr.removeUser(userId); user = mgr.getUser(userId); if (user != null) {
fail(\User object found in database!\);
} }
这个测试实际上是一个集成测试(integration test),而不是单元测试(unit test)。
Downloads By http://down.liehuo.net
http://www.elecfans.com 电子发烧友 http://bbs.elecfans.com 电子技术论坛
为了更接近单元测试,可以使用EasyMock或是类似工具来“伪装”(fake) DAO。这样,就不必关心ApplictionContext和任何依赖Spring API 的东西。建议在测试项目依赖(Hibernate,Spring,自己的类)的内部构件,包括数据库。第9章,讨论重构UserManagerTest,使用mock解决DAO的依赖性。
3.为了编译UserManagerTest,在src/org/appfuse/service中新建一个接口──UserManager。在org.appfuse.service包中创建这个类,代码如下:
package org.appfuse.service; // use your IDE to handle imports public interface UserManager { public List getUsers();
public User getUser(String userId); public User saveUser(User user); public void removeUser(String userId); }
4.建一个名为org.appfuse.service.impl的子包,新建一个类实现UserManager 接口的。
package org.appfuse.service.impl; // use your IDE to handle imports
public class UserManagerImpl implements UserManager {
private static Log log = LogFactory.getLog(UserManagerImpl.class); private UserDAO dao;
public void setUserDAO(UserDAO dao) { this.dao = dao; }
public List getUsers() { return dao.getUsers(); }
public User getUser(String userId) {
User user = dao.getUser(Long.valueOf(userId)); if (user == null) {
Downloads By http://down.liehuo.net
http://www.elecfans.com 电子发烧友 http://bbs.elecfans.com 电子技术论坛
log.warn(\UserId '\ + userId + \' not found in database.\);
}
return user; }
public User saveUser(User user) { dao.saveUser(user); return user;}
public void removeUser(String userId) { dao.removeUser(Long.valueOf(userId)); } }
这个类看不出你在使用Hibernate。当你打算把持久层转向一种不同的技术时,这样做很重要。
这个类提供一个私有dao成员变量,和setUserDAO方法一样。这样能够让Spring能够表演“依赖性绑定”魔术(perform “dependency binding” magic),把这些对象扎在一起。在使用mock重构这个类时,你必须在UserManager接口中添加serUserDAO 方法。
5.在进行测试之前,配置Spring,让getBeans返回一个UserManagerImpl类。在web/WEB-INF/applicationContext.xml文件中,添加以下几行:
唯一的问题,你还没有使Spring的AOP,特别是声明式的事务处理发挥作用。6.为了达到目的,使用ProxyFactoryBean代替userManager。ProxyFactoryBean是一个类的不同的实现,这样AOP 能够解释和覆盖调用的方法。在事务处理中,使用
TransactionProxyFactoryBean代替UserManagerImpl 类。在context文件中添加下面bean的定义:
class=\org.springframework.transaction.interceptor.TransactionProxyFactoryBean\> Downloads By http://down.liehuo.net http://www.elecfans.com 电子发烧友 http://bbs.elecfans.com 电子技术论坛
从这个xml代码片断中可以看出,TransactionProxyFactoryBean必须有一个transactionManager 属性设置和transactionAttributes 定义。
7.让事务处理代理服务器(Transaction Proxy)知道你要模仿的对象:
userManagerTarget。作为新bean的一部分,把原来的userManager bean改成拥有一个userManagerTarget的id属性。
编辑applictionContext.xml添加 userManager 和 userManagerTarget 的定义后,运行ant test -Dtestcase=UserManager ,看看终端输出:
8.如果你想看看事务处理的执行和提交情况,在log4j.xml中添加:
Downloads By http://down.liehuo.net
http://www.elecfans.com 电子发烧友 http://bbs.elecfans.com 电子技术论坛
重新运行测试,将看到大量日志信息,如它相关的对象,事务的创建和提交等。测试完毕,最好删除上面的日志定义(logger)。
祝贺你!你已经实现了一个web应用的Spring/Hibernate后端解决方案。并且你已经用AOP和声明式业务处理配置好了业务代理。了不起,自我鼓励一下!(This is no smallfeat; give yourself a pat on the back!)