0

当前的问题

请参考相关帖子:hibernate 域类中会出现什么问题——因此我们需要(单元)测试它们? 在我的新 J2EE 项目中,我正在尝试测试(不一定是单元测试)我开始编写的域对象。它们不涉及太多业务逻辑(业务逻辑是 DAO 对象之上的业务服务的一部分),通过测试,我本质上是在确保域对象的完整性,我尝试通过测试 DAO 来做到这一点方法。请注意,我不能使用 JUnit 等测试域对象,因为在我的情况下它们没有任何方法,并且它们具有属性和休眠映射注释。

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

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

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

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

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

问题

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

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

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

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

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

感谢您的评论和对如此冗长的帖子的歉意。

4

1 回答 1

1

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

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