【问题标题】:Automated testing of domain classes (Not unit testing)领域类的自动化测试(不是单元测试)
【发布时间】:2013-11-11 23:15:53
【问题描述】:

当前问题

请参考相关帖子:What can go wrong in hibernate domain classes – so that we need to (unit) test them? 在我的新 J2EE 项目中,我正在尝试测试(不一定是单元测试)我开始编写的域对象。它们不涉及太多业务逻辑(业务逻辑是 DAO 对象之上的业务服务的一部分),通过测试,我本质上是在确保域对象的完整性,我尝试通过测试 DAO 来做到这一点方法。请注意,我不能使用 JUnit 等测试域对象,因为在我的情况下它们没有任何方法,并且它们具有属性和休眠映射注释。

例如,让我考虑 Patient 域对象。 PatientDAO 在这种情况下正在处理 Patient 域对象的 CRUD 操作。以下是方法(不完整,打算稍后添加更多以测试边界条件)。

注意:我不是将这些称为单元测试用例,它们可能是小型集成测试等。我很好,这种方法适用于测试域对象。

PatientDAOTest 类包含: - testCreatePatient(); - 测试更新患者(); - testFindPatient(); - testDeletePatient();

PatientDAO 类包含: - createPatient(); - 更新病人(); - 查找病人(); - deletePatient();

让我们考虑在域对象中测试 updateMethod() 的 testUpdatePatient() 方法。现在,我将如何实现 testUpdatePatient() 方法?好吧,我在想: 1. 使用 'findPatient()' 域方法获取现有患者 2. 使用新的详细信息更新患者记录 3. 使用 'updatePatient()' 域方法将其保存回数据库 4. 使用“findPatient()”域方法从数据库中检索患者记录 5. 断言更新数据

问题

如您所见,我在测试中使用了数据库,这很好,但是这种方法有什么问题吗?

我对这种方法的真正问题(读作问题)是什么?

我需要在测试 'updatePatient()' 时使用 'findPatient()' 方法(实际上是 2 次)。这是我不喜欢的,事实上我必须在测试方法时使用另一种方法,而另一种方法本身可能有问题。当我也尝试测试其他 CRUD 方法时,同样的故事会重复。

另外,我可以编写 select sql 查询以从数据库中获取患者记录,以便从测试方法中断言(在触发更新后),但这只是违背了使用休眠的全部目的(以减少 SQL 编码工作) ,因此,我不喜欢这种方法。

我的问题是,依赖其他方法来测试特定方法是很常见的,这是不是一个不错的方法?如果这是错误的,我应该如何在我的域对象中实际测试 ORM 映射。

感谢您的 cmets 并为这么长的帖子道歉。

【问题讨论】:

    标签: hibernate unit-testing


    【解决方案1】:

    根据我的经验,您主要关心的问题的答案很简单,但这里还有其他几个概念问题。

    1. 完全可以在另一个功能 (updatePatient) 的测试中包含使用功能 (findPatient),但前提是您有另一个测试,仅涵盖 findPatient 本身。
    2. 对于 DB 集成测试的系统部分,您可以考虑使用专用的自动测试 DB,清除所有数据并将其初始化为所需的状态作为单元测试的设置。使用纯 SQL 脚本(TRUNCATE TABLE 患者;INSERT INTO 患者 ...)用示例初始数据初始化您的数据库 - 我以前做的是在几个命名的数据库初始数据状态之间切换(例如“cleanDB”、“twoPatientsSimple1”、“twoPatientsLenkedToInsuranceContracts1 “ ETC。)。这里的重点是,您的数据库在单元测试期间被更改,并且使用纯 ROLLBACK 进入测试之前的状态并不能确保您想要的确切状态(例如,您可能在测试期间明确提交,并且您的数据进入不同于初始状态)。您还可以包含测试以确保在测试更改数据库状态后再次使用纯 SQL。使用这种方法进行测试通常执行缓慢且难以维护(除非您拥有一组我们自己的辅助工具),但它让您对自己的数据和行为充满信心。在您清楚地完成此操作后,它会在 UI/功能测试期间为您节省大量时间和混乱。听起来可能很可怕,但是当您稍微使用它时,您最终会得到一组简单的 DB 状态数据(例如,在测试用例中表示为 TSV/CSV)“initState”和“expectedState”,而您只需使用这些在测试行为之前/之后初始化/比较的状态。
    3. 对于域对象的真正单元测试(未与 DB 集成),您必须模拟您的 DAO/Repository/DataMapper 类,例如使用简单的 List 泛型(createPatient 将其添加到列表中等)
    4. 对于 ORM 本身(您自己的、第 3 方或您的扩展)的集成测试,您可以使用第 2 点中的方法和一些足够复杂的示例数据(不一定是您的域对象),让您对你的 ORM 是如何工作的。例如。 Microsoft Entity Framework 在早期阶段的工作非常不可预测,因此为您通常使用的功能编写完整的集成测试可以避免调试 ORM 本身的错误和问题,并向您展示 ORM 在各种条件下的准确行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多