`
fangzhouxing
  • 浏览: 213306 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JBoss Seam (POJO without EJB) 后台 + ExtJS 前台完整例子(十二)

阅读更多

JBoss Seam (POJO without EJB) 后台 + ExtJS 前台完整例子(十二)


1.引言

测试驱动开发(Test-Driven Development)的基本思路就是通过测试来推动整个开发的进行。设计思路定下来以后,先编写测试程序,然后再实现被测试的功能。这个习惯的形成将显著地提高软件的质量。

针对服务层的单元测试,本项目构建了一个完整的测试环境。本文介绍测试环境构建的设计思路。

2.单元测试应该测试什么?

这篇文章中,介绍了本项目的分层设计方法。作为设计原则,远程外观和Servlet中不应该有太多的业务逻辑,具体功能必须由服务层实现。因此我认为没有必要对远程外观和Servlet进行测试。

我在本项目中提倡的领域模型层的设计,基本上可以归为所谓“贫血领域模型”(Anemic Domain Model)这种架构模式,因为没有太多的领域逻辑,所以也不必去对它们做单元测试了。

最后,真正需要单元测试的就剩下了服务层!本项目围绕服务层构建了一个完整的单元测试环境。

3.测试环境设计

由于遵循POJO without EJB设计原则,本项目中的单元测试是在完全脱离Seam框架下进行的。测试环境设计的要点说明如下:

(1)测试数据库和开发数据库分开,用Ant目标切换:
xml 代码
  1. <target name="copy-config-dev" >
  2. <concat destfile="WEB-INF/src/hibernate.cfg.xml">
  3. <filelist dir="config/db" files="head.xml" />
  4. <filelist dir="config/db" files="datasource-dev.xml" />
  5. <filelist dir="config/db" files="sample.xml" />
  6. <filelist dir="config/db" files="end.xml" />
  7. <!---->concat>
  8. <!---->target>
  9. <target name="copy-config-test" >
  10. <concat destfile="WEB-INF/src/hibernate.cfg.xml">
  11. <filelist dir="config/db" files="head.xml" />
  12. <filelist dir="config/db" files="datasource-test.xml" />
  13. <filelist dir="config/db" files="sample.xml" />
  14. <filelist dir="config/db" files="end.xml" />
  15. <!---->concat>
  16. <!---->target>

程序员需要自己手工配置好 config/db 目录下的两个数据源配置文件,datasource-dev.xml 用于开发,datasource-test.xml用于测试。

(2)为每一个子系统设计一个 XXXTestCase 类,全部服务层测试类扩展这个类。XXXTestCase 类的主要任务是准备测试数据:

java 代码
  1. public class SampleTestCase extends BaseTestCase {
  2. @BeforeMethod
  3. @Override
  4. public void begin() {
  5. super.begin();
  6. initTableData();
  7. }
  8. /**
  9. * 单元测试前让数据库表处于初始状态
  10. */
  11. protected void initTableData() {
  12. exec("DELETE FROM Booking");
  13. exec("DELETE FROM Customer");
  14. exec("DELETE FROM Hotel");
  15. exec("DELETE FROM T_NextId");
  16. }
  17. /**
  18. * 准备测试数据:Customer
  19. */
  20. protected void insert2User() {
  21. exec("insert into Customer (username, password, name) values ('gavin', 'foobar', 'Gavin King')");
  22. exec("insert into Customer (username, password, name) values ('demo', 'demo', 'Demo User')");
  23. }
  24. 。。。
  25. }

我采用了最灵活的一种方式来准备测试数据,就是SQL语句。由于Hibernate会生成数据库表之间的参照完整性约束, 因此,程序员在编写SQL脚本时应该考虑到这一点。

(3)服务层的单元测试程序,由于继承了 XXXTestCase 类,可以集中于要测试的业务逻辑,例如:
java 代码
  1. public class UserServiceTest extends SampleTestCase {
  2. private UserService _userService;
  3. @BeforeClass
  4. @Override
  5. public void init() {
  6. super.init();
  7. _userService = new UserService();
  8. }
  9. @BeforeMethod
  10. @Override
  11. public void begin() {
  12. super.begin();
  13. _userService.setSession(session);
  14. }
  15. @Test
  16. public void canLogin() {
  17. insert2User();
  18. assert _userService.login("demo", "demo");
  19. assert _userService.getUser().getUsername().equals("demo");
  20. assert !_userService.login("demo", "demo2");
  21. }
  22. 。。。
  23. }

4.单元测试编程时需要注意的问题

编写单元测试程序时,需要注意下列问题:

(1)作为服务层设计的原则之一,禁止事务提交行为,因此,需要在单元测试方法中手工提交事务,如:

java 代码
  1. @Test
  2. public void canChangePassword() {
  3. insert2User();
  4. User user = _userService.find("demo");
  5. _userService.setUser(user);
  6. _userService.changePassword("demo2");
  7. session.flush(); //使事务提交
  8. assert _userService.find("demo").getPassword().equals("demo2");
  9. }

(2)为了模拟Seam框架的对象注入,在服务层类中,需要为单元测试专门额外添加 setter 方法,例如:

java 代码
  1. @BeforeMethod
  2. @Override
  3. public void begin() {
  4. super.begin();
  5. _hotelService.setSession(session); //额外增加了setSession方法,专门用于单元测试
  6. }

5.结语

本项目所用的单元测试环境构建方法,是我对以往项目经验的基础上设计的,经过实践检验是可行的。

这是本系列文章的最后一篇。下面是所有文章的完整列表:
(1)下载示例项目并安装运行
(2)建立Eclipse开发环境
(3)熟悉项目中与JSF相关内容
(4)重新认识JS
(5)ExtJS之表单(Form)
(6)ExtJS之布局(Layout)
(7)ExtJS之网格(Grid)
(8)Java后台和前台的通讯机制
(9)Seam框架简化Java开发
(10)分层架构设计
(11)安全性
(12)单元测试

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics