实体类PasswordTicket代表一个重置口令的请求:
@Entity @Table(name="T_PWDT") public class PasswordTicket { private String id; private User user; private String ticket; private long createdDate; @Id @Column(nullable=false, updatable=false, length=32) @GeneratedValue(generator="system-uuid") @GenericGenerator(name="system-uuid", strategy="uuid") public String getId() { return id; } protected void setId(String id) { this.id = id; } @ManyToOne @JoinColumn(nullable=false, updatable=false) public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Column(nullable=false, updatable=false, length=32) public String getTicket() { return ticket; } public void setTicket(String ticket) { this.ticket = ticket; } @Column(nullable=false, updatable=false) public long getCreatedDate() { return createdDate; } public void setCreatedDate(long createdDate) { this.createdDate = createdDate; } }
|
UserDao接口定义了对用户的相关操作:
public interface UserDao { User queryForSignOn(String username); User queryUser(String username); void createUser(User user); void updateUser(User user); boolean updateEmailValidation(String username, int ticket); String createPasswordTicket(User user); boolean updatePassword(String username, String oldPassword, String newPassword); boolean queryResetPassword(User user, String ticket); boolean updateResetPassword(User user, String ticket, String password); void updateLock(User user, long lockTime); void updateUnlock(User user); }
|
UserDaoImpl是其实现类:
public class UserDaoImpl implements UserDao { public User queryForSignOn(String username) { User user = queryUser(username); if(user.getLocked()) throw new LockException(user.getLockDate()); return user; } public User queryUser(String username) { return (User) HibernateUtil.query(User.class, username); } public void createUser(User user) { user.setEmailValidation((int)(Math.random() * 1000000) + 0xf); HibernateUtil.createEntity(user); } // 其余方法略 ... }
|
由于将Hibernate事务绑定在Thread上,因此,实际的客户端调用DAO组件时,还必须加入事务代码:
Transaction tx = HibernateUtil.getCurrentSession().beginTransaction(); try { dao.xxx(); tx.commit(); } catch(Exception e) { tx.rollback(); throw e; }
|
下面,我们开始对DAO组件编写单元测试。前面提到了HSQLDB这一小巧的纯Java数据库。HSQLDB除了提供完整的JDBC驱动以及事务支持外,HSQLDB还提供了进程外模式(与普通数据库类似)和进程内模式(In-Process),以及文件和内存两种存储模式。我们将HSQLDB设定为进程内模式及仅使用内存存储,这样,在运行JUnit测试时,可以直接在测试代码中启动HSQLDB。测试完毕后,由于测试数据并没有保存在文件上,因此,不必清理数据库。
此外,为了执行批量测试,在每个独立的DAO单元测试运行前,我们都执行一个初始化脚本,重新建立所有的表。该初始化脚本是通过HibernateTool自动生成的,稍后我们还会讨论。下图是单元测试的执行顺序:
 |
| 图2 |