gpt4 book ai didi

unit-testing - 如何使用 Mocks 避免重复逻辑

转载 作者:行者123 更新时间:2023-12-04 04:13:50 25 4
gpt4 key购买 nike

我有以下挑战,但我还没有找到好的答案。我正在使用 Mocking 框架(在本例中为 JMock)以允许将单元测试与数据库代码隔离。我正在模拟对涉及数据库逻辑的类的访问,并使用 DBUnit 单独测试数据库类。

我遇到的问题是我注意到一种模式,其中逻辑在多个地方概念上重复。例如,我需要检测数据库中的值不存在,因此在这种情况下我可能会从方法返回 null。所以我有一个数据库访问类,它执行数据库交互,并适本地返回 null。然后我有业务逻辑类,它从模拟中接收空值,然后如果值为空值则进行测试以采取适当的行动。

现在,如果将来该行为需要更改并且返回 null 不再合适,例如因为状态变得更加复杂,所以我需要返回一个报告该值不存在的对象以及来自数据库。

现在,如果我将数据库类的行为更改为在这种情况下不再返回 null,则业务逻辑类仍会显示为正常运行,并且该错误只会在 QA 中被捕获,除非有人记得耦合,或正确遵循方法的用法。

我觉得我遗漏了一些东西,必须有更好的方法来避免这种概念上的重复,或者至少对其进行测试,以便如果它发生更改,则更改未传播的事实无法通过单元测试。

有什么建议?

更新:

让我试着澄清我的问题。我在考虑当代码随着时间的推移而演变时,如何确保通过模拟测试的类和模拟所代表的类的实际实现之间的集成不会中断。

例如,我刚刚有一个案例,我有一个最初创建的方法并且不期望空值,所以这不是对真实对象的测试。然后类的用户(通过模拟测试)被增强为在某些情况下传入一个 null 作为参数。在集成失败时,因为没有对真正的类进行 null 测试。现在,当最初构建这些类时,这没什么大不了的,因为您在构建时正在测试两端,但是如果设计需要在两个月后演变而您往往会忘记细节,那么您将如何测试之间的交互?这两组对象(通过模拟与实际实现测试的对象)?

潜在的问题似乎是重复(即违反 DRY 原则)之一,期望确实保留在两个地方,虽然关系是概念上的,但没有实际的重复代码。

[在 Aaron Digulla 对他的回答进行第二次编辑后进行编辑]:

对,这正是我正在做的事情(除了通过 DBUnit 测试并在测试期间与数据库交互的类中与 DB 进一步交互,但它是相同的想法)。所以现在,假设我们需要修改数据库行为,以便结果不同。使用模拟的测试将继续通过,除非 1)有人记得或 2)它在集成中中断。因此,数据库的存储过程返回值(比如说)在模拟的测试数据中基本上是重复的。现在让我烦恼的是重复逻辑是重复的,这是对 DRY 的微妙违反。可能就是这样(毕竟集成测试是有原因的),但我觉得我错过了一些东西。

[编辑开始赏金]

阅读与 Aaron 的互动达到了问题的重点,但我真正想要的是对如何避免或管理明显重复的一些见解,以便真实类(class)行为的变化将显示在与模拟交互的单元测试作为破坏的东西。显然这不会自动发生,但可能有一种方法可以正确设计场景。

[编辑奖励赏金]

感谢所有花时间回答问题的人。获胜者教会了我一些关于如何思考如何在两层之间传递数据的新知识,并首先得到了答案。

最佳答案

你从根本上要求不可能的事情。您要求您的单元测试在您更改外部资源的行为时预测并通知您。不编写测试来产生新行为,他们怎么知道?

您所描述的是添加一个必须进行测试的全新状态 - 而不是空结果,现在有一些对象从数据库中出来。你的测试套件怎么可能知道被测对象的预期行为对于一些新的随机对象应该是什么?您需要编写一个新的测试。

正如您评论的那样,模拟不是“行为不端”。模拟正在做你设置它要做的事情。规范更改的事实对模拟没有影响。这种情况下唯一的问题是实现更改的人忘记更新单元测试。我实际上不太确定为什么您认为存在任何重复的担忧。

向系统添加一些新返回结果的编码器负责添加单元测试来处理这种情况。如果该代码也 100% 确定现在不可能返回空结果,那么他也可以删除旧的单元测试。但你为什么要这样做?单元测试正确地描述了被测对象在收到空结果时的行为。如果将系统后端更改为某个确实返回空值的新数据库,会发生什么情况?如果规范变回返回 null 怎么办?您不妨保留测试,因为就您的对象而言,它确实可以从外部资源中取回任何东西,并且应该优雅地处理所有可能的情况。

模拟的全部目的是将您的测试与真实资源分离。它不会自动使您免于将错误引入系统。如果您的单元测试准确地描述了接收空值时的行为,那太好了!但是这个测试不应该知道任何其他状态,当然也不应该以某种方式被告知外部资源将不再发送空值。

如果您进行适当的松散耦合设计,您的系统可以拥有您能想象到的任何后端。您不应该只考虑一种外部资源来编写测试。如果您添加一些使用真实数据库的集成测试,从而消除模拟层,听起来您可能会更高兴。这对于进行构建或健全性/烟雾测试始终是一个好主意,但通常会阻碍日常开发。

关于unit-testing - 如何使用 Mocks 避免重复逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/643410/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com