服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

利用hsqldb进行hibernate的单元测试二


  因为所有代码(经过单元测试的产品级代码)都是从hibernateutil获取hibernate会话,所以能在同一个位置对其进行配置。为了对代码的第一位进行单元测试而访问testschema类将会激活静态初始化程序,该程序将安装hibernate并且将测试sessionfactory插入到hibernateutil中。对于产品级代码,可以使用标准hibernate.cfg.xml配置机制来初始化 sessionfactory。
  
  那么单元测试中的外部特征是什么?下面的测试代码片段是用来检查逻辑的,决定运动员在棒球联盟比赛中是哪个位置的人选:
  
  public void testgeteligiblepositions() throws exception {
  player player = new player("playerid");
  testschema.addplayer(player);
  
  fieldingstint stint1 = new fieldingstint
  ("playerid", 2004, "sea", position.catcher);
  stint1.setgames(20);
  testschema.addfieldingstint(stint1);
  
  set<position> positions = player.geteligiblepositions(2004);
  assertequals(1, positions.size());
  asserttrue(positions.contains(position.catcher));
  }
  
  第一次创建新player实例并通过addplayer()方法添加到testschema中。必须首先完成此步骤,因为fidldstint类和player类之间有外键关系。如果不首先添加该实例,在设法添加fieldingstint时将会出现外键约束违例。
  
  一旦测试上下文就位,就可以测试geteligiblepositions()方法来检索校正数据。下面是在tsetschema中addplayer()方法的代码。您将注意到使用hibernate而不是bare-metal jdbc代码:
  
  public static void addplayer(player player) {
  if (player.getplayerid() == null) {
  throw new illegalargumentexception("no primary key specified");
  }
  
  session session = hibernateutil.getsession();
  transaction transaction = session.begintransaction();
  try {
  session.save(player, player.getplayerid());
  transaction.commit();
  }
  finally {
  session.close();
  }
  }
  
  在单元测试中最重要的就是要保持测试实例是独立的。因为该方法仍然涉及数据库,所以需要一种方法在每个测试实例之前清理数据库。在我的数据库架构中有四个表,所以我在testschemaz上编写了reset()方法,该方法从使用jdbc的表中删除所有行。注意,因为hsqldb能识别外键,删除表的顺序是很重要的,下面是代码:
  
  public static void reset() throws schemaexception {
  session session = hibernateutil.getsession();
  try {
  connection connection = session.connection();
  try {
  statement statement = connection.createstatement();
  try {
  statement.executeupdate("delete from batting");
  statement.executeupdate("delete from fielding");
  statement.executeupdate("delete from pitching");
  statement.executeupdate("delete from player");
  connection.commit();
  }
  finally {
  statement.close();
  }
  }
  catch (hibernateexception e) {
  connection.rollback();
  throw new schemaexception(e);
  }
  catch (sqlexception e) {
  connection.rollback();
  throw new schemaexception(e);
  }
  }
  catch (sqlexception e) {
  throw new schemaexception(e);
  }
  finally {
  session.close();
  }
  }
  当确定在hibernate 3.0中进行大量删除操作时,应该能从应用程序中删除直接jdbc的最后一位。到此时为止,必须获取数据库连接并向数据库直接提交sql。
  
  在确保没有关闭连接的情况下,为了释放资源,只关闭会话就足够了。出于手工编写许多jcbc代码来进行开发的习惯,第一个版本关闭了jdbc连接。因为通过配置hibernate创建的连接池只带有一个链接,在第一个之后就完全破坏了测试。一定要注意这种情况!
  
  既然在测试类运行时(设想运行所有的测试实例)不能确定数据库的状态,应该在setup()方法中包含数据库清除,如下所示:
  
  public void setup() throws exception {
  testschema.reset();
  }
  
  结束语
  
  在使用像hibernate这种复杂的o/r映射程序时,必须能够测试实际存在(real-live)的rdbms,而不会发生任何针对已部署数据库的争论。虽然hibernate有内置模式生成工具,让此类测试特别简单,但是在这里展示的例子并不排除hibernate,并且可能与jdo或toplink一起运行。使用上面描述的设置,您不必离开舒适的ide环境,但仍然可以对代码进行大量测试。

扫描关注微信公众号