Spring,Hibernate和AbstractTransactionalJUnit4SpringContextTests:无法找到具有多个映射到同一底层数据的对象

时间:2012-10-24 14:14:55

标签: java spring hibernate junit

我使用AbstractTransactionalJUnit4SpringContextTests成功为Spring 2.5.6 / Hibernate 3.5.3项目创建了许多与数据库相关的单元测试。例如,创建Device对象,然后验证所有Device对象列表中包含相同的对象:

@ContextConfiguration(locations = { "classpath:/UnitTests-context.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class DeviceDaoTests extends AbstractTransactionalJUnit4SpringContextTests {

    @Test
    public void testGetDeviceList() {
        Device device = new Device();
        this.sessionFactory.getCurrentSession().merge(device);

        Query myQuery = this.sessionFactory.getCurrentSession().createQuery("from Device");
        List<Device> allDevices = myQuery.list();
        assertTrue(allDevices.contains(device);
    }
}

此测试有效。

Device类,映射到名为DEVICES的表:

@Entity
@Table(name = "DEVICES")
public class Device {

//properties omitted for brevity and readability

}

还有一个名为DeviceListItem的类,它映射到名为DEVICESLIST_VIEW的数据库视图,其中包含DEVICES表的一部分(以及其他表):

@Entity
@Table(name = "DEVICESLIST_VIEW")
public class DeviceListItem {

//properties omitted for brevity and readability

}

现在,如果我想测试在数据库中插入一个Device导致从所有DeviceListItem对象的列表中找到具有相同id的DeviceListItem(类似于第一个测试),则存在问题 - 以下测试失败:

   @Test
   public void testGetDeviceListItemList() {
      Device device = new Device();
      this.sessionFactory.getCurrentSession().merge(device);

      Query myQuery = this.sessionFactory.getCurrentSession().createQuery("from DeviceListItem");
      List<DeviceListItem> allDeviceListItems = myQuery.list();
      assertTrue(allDeviceListItems.get(0).getId().equals(device.getId())
  }

在Web服务器上运行应用程序时,所有映射,DAO类等都起作用 - 只有前面提到的单元测试失败。这可能是因为保存了一个类型为Device的新对象,但读取的项目类型为DeviceListItem,而Hibernate并不“知道”它们都引用相同的底层数据库表,并且因为这些对象并未真正保存到数据库中。

有没有办法让这个测试工作,即测试将Device对象写入数据库并从数据库中读取为DeviceListItem对象的场景?

(请注意,代码示例中可能存在拼写错误,样式问题等,因为示例非常简化,不一定是从实际执行的代码中复制/粘贴)

1 个答案:

答案 0 :(得分:0)

通过添加注释解决

@Rollback(false)

(参见http://static.springsource.org/spring/docs/2.5.6/reference/testing.html)方法

testGetDeviceListItemList

(见原始问题)。但是,这也意味着Spring Unit测试上下文不会自动回滚,所以我必须确保手动后数据库状态恢复正常:

this.sessionFactory.getCurrentSession().delete(device);

完整方法:

       @Rollback(false)
       @Test
       public void testGetDeviceListItemList() {
          Device device = new Device();
          this.sessionFactory.getCurrentSession().merge(device);

          Query myQuery = this.sessionFactory.getCurrentSession().createQuery("from DeviceListItem");
          List<DeviceListItem> allDeviceListItems = myQuery.list();
          assertTrue(allDeviceListItems.get(0).getId().equals(device.getId());

          this.sessionFactory.getCurrentSession().delete(device);
      }