1

我已经使用AbstractTransactionalJUnit4SpringContextTests成功地为 Spring 2.5.6/Hibernate 3.5.3 项目创建了许多与数据库相关的单元测试。一个示例,其中创建了一个设备对象,然后验证同一对象是否包含在所有设备对象的列表中:

@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

}

现在,如果我想测试在数据库中插入设备会导致从所有 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 对象从数据库中读取的场景?

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

4

1 回答 1

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);
      }
于 2012-10-24T15:49:26.093 回答