热点推荐:ASP.Net | ADO.Net | VB.Net | Web服务器 | Access | MSSQL | MySQL | Oracle | .Net控件 | Win 9x | Win 2000 | Win 2003 | DOS | Unix | 注册表 | 应用其它 | 安装调试 | 基本操作 | 使用技巧 | 系统优化 |故障处理 | 个性风格 | 病毒安全 | 专杀工具
您现在的位置: 中华IT技术网 >> Java >> J2EE >> 正文
全文
对J2EE中的DAO组件编写单元测试
作者:1024k    文章来源:本站原创    更新时间:2007-11-21

单元测试作为保证软件质量及重构的基础,早已获得广大开发人员的认可。单元测试是一种细粒度的测试,越来越多的开发人员在提交功能模块时也同时提交相应的单元测试。对于大多数开发人员来讲,编写单元测试已经成为开发过程中必须的流程和最佳实践。
  对普通的逻辑组件编写单元测试是一件容易的事情,由于逻辑组件通常只需要内存资源,因此,设置好输入输出即可编写有效的单元测试。对于稍微复杂一点的组件,例如Servlet,我们可以自行编写模拟对象,以便模拟HttpRequest和HttpResponse等对象,或者,使用EasyMock之类的动态模拟库,可以对任意接口实现相应的模拟对象,从而对依赖接口的组件进行有效的单元测试。

  在J2EE开发中,对DAO组件编写单元测试往往是一件非常复杂的任务。和其他组件不通,DAO组件通常依赖于底层数据库,以及JDBC接口或者某个ORM框架(如Hibernate),对DAO组件的测试往往还需引入事务,这更增加了编写单元测试的复杂性。虽然使用EasyMock也可以模拟出任意的JDBC接口对象,或者ORM框架的主要接口,但其复杂性往往非常高,需要编写大量的模拟代码,且代码复用度很低,甚至不如直接在真实的数据库环境下测试。不过,使用真实数据库环境也有一个明显的弊端,我们需要准备数据库环境,准备初始数据,并且每次运行单元测试后,其数据库现有的数据将直接影响到下一次测试,难以实现“即时运行,反复运行”单元测试的良好实践。

  本文针对DAO组件给出一种较为合适的单元测试的编写策略。在JavaEE开发网的开发过程中,为了对DAO组件进行有效的单元测试,我们采用HSQLDB这一小巧的纯Java数据库作为测试时期的数据库环境,配合Ant,实现了自动生成数据库脚本,测试前自动初始化数据库,极大地简化了DAO组件的单元测试的编写。
在Java领域,JUnit作为第一个单元测试框架已经获得了最广泛的应用,无可争议地成为Java领域单元测试的标准框架。本文以最新的JUnit 4版本为例,演示如何创建对DAO组件的单元测试用例。

  JavaEEdev的持久层使用Hibernate 3.2,底层数据库为MySQL。为了演示如何对DAO进行单元测试,我们将其简化为一个DAOTest工程:

  由于将Hibernate的Transaction绑定在Thread上,因此,HibernateUtil类负责初始化SessionFactory以及获取当前的Session:

 public class HibernateUtil {
  private static final  SessionFactory sessionFactory;
  static {
  try {
  sessionFactory =  new AnnotationConfiguration()
  .configure()
  .buildSessionFactory();
  }
  catch(Exception e) {
  throw new  ExceptionInInitializerError(e);
  }
  }
  public static Session  getCurrentSession() {
  return  sessionFactory.getCurrentSession();
  }
  }

HibernateUtil还包含了一些辅助方法,如:   public static Object query(Class clazz, Serializable id);
  public static void createEntity(Object entity);
  public static Object queryForObject(String hql, Object[] params);
  public static List queryForList(String hql, Object[] params);
 
  在此不再多述。
  实体类User使用JPA注解,代表一个用户:
  @Entity
  @Table(name="T_USER")
  public class User {
  public static final  String REGEX_USERNAME = "[a-z0-9][a-z0-9\\-]{1,18}[a-z0-9]";
  public static final  String REGEX_PASSWORD = "[a-f0-9]{32}";
  public static final  String REGEX_EMAIL = "([0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+[a-zA-Z]{2,9})"; 
  private String  username;     // 用户名
  private String  password;     // MD5口令
  private boolean  admin;       // 是否是管理员
  private String  email;        // 电子邮件
  private int  emailValidation; // 电子邮件验证码
  private long  createdDate;    // 创建时间
  private long  lockDate;       // 锁定时间  
  public User() {} 
  public User(String  username, String password, boolean admin, long lastSignOnDate) {
  this.username = username;
  this.password =  password;
  this.admin = admin;
  } 
  @Id
  @Column(updatable=false,  length=20)
  @Pattern(regex=REGEX_USERNAME)
  public String  getUsername() { return username; }
  public void setUsername(String  username) { this.username = username; } 
  @Column(nullable=false,  length=32)
  @Pattern(regex=REGEX_PASSWORD)
  public String  getPassword() { return password; }
  public void  setPassword(String password) { this.password = password; } 
  @Column(nullable=false,  length=50)
  @Pattern(regex=REGEX_EMAIL)
  public String getEmail()  { return email; }
  public void  setEmail(String email) { this.email = email; } 
  @Column(nullable=false)
  public boolean getAdmin()  { return admin; }
  public void  setAdmin(boolean admin) { this.admin = admin; } 
  @Column(nullable=false,  updatable=false)
  public long  getCreatedDate() { return createdDate; }
  public void  setCreatedDate(long createdDate) { this.createdDate = createdDate; } 
  @Column(nullable=false)
  public int  getEmailValidation() { return emailValidation; }
  public void  setEmailValidation(int emailValidation) { this.emailValidation =  emailValidation; } 
  @Column(nullable=false)
  public long getLockDate()  { return lockDate; }
  public void  setLockDate(long lockDate) { this.lockDate = lockDate; }
  @Transient
  public boolean  getEmailValidated() { return emailValidation==0; } 
  @Transient
 

[1] [2] 下一页

相关文章
最新更新
编辑推荐
热门图片
频道大全
文章阅读排行
周排行
月排行