使用模拟是否是一种好的编程实践还是只是一种不同的方法?

5

你们认为使用模拟对象比不使用模拟对象更好吗?模拟对象仅用于单元测试还是可以直接在原始项目中用作真实对象并在之后切换?

我一直在这里读书,最吸引我的是模拟的层隔离。

3个回答

6
模拟在单元测试中绝对是有用的。当你想要隔离测试A依赖于B时,就需要使用模拟B(带有预期的输入/输出)来测试A。确保你单独测试B,以确保它是正确的。
在动态语言中,它们并不是严格必需的。但是,模拟框架可以帮助您验证对模拟设置的期望是否得到满足。
你永远不应该将模拟用作真正的实现。这种行为是笑话的素材。"我们只需模拟整个应用程序!耶!"这就是接口/等效物的用途...

1
另一个有用的模拟功能是它们通常比真实环境更容易设置(特别是如果真实环境与数据库相关),这使得运行测试变得更快。 - Amber
当你说我不应该将模拟用作真实实现时,你是指我只应该在想要测试的真实对象之外使用模拟,还是仅仅是说我永远不应该将模拟用作最终产品 - 这显然是不对的。假设我有一个在类A中调用类B的真实方法,那么在真实的类A中模拟类B是否可以,或者我应该在测试类中测试并设置真实的类A和模拟的类B? - Arturo
@arturo 你只是在单元测试的情境下做嘲讽。 - hvgotcodes
1
+1!虽然在开发过程中可以使用模拟或伪造对象来允许您在Web服务或其他依赖项未完成时演示或UI测试应用程序。 - TrueWill

6

归根结底,可以认为它是“另一种实现方式”。在缺乏mocking的情况下,软件已经被编写了数十年,并且仍在继续编写。

这主要是单元测试的一个设施。

Mocking/stubs真正优秀的地方在于测试驱动开发。在没有mocking/stubbing的情况下,应用程序中依赖关系的网状结构通常是这样的:在编写测试之前,您必须几乎构建整个应用程序,即使这样,您也正在测试更大的功能部分,因此隔离错误变得更加困难。

考虑以下内容:

  • 我想创建 ClassA 并编写测试以验证其行为。
  • 我开始编写测试(先测试驱动来引出设计)。
  • 糟糕,ClassA 需要从 RepositoryM 获取数据。
  • 我将实现 RepositoryM 以便测试 ClassA
  • 哦,但是首先让我们为 RepositoryM 编写测试。
  • 该死,RepositoryM 实际上需要 ServiceX 来填充其数据。
  • 我将实现 ServiceX ,以便我可以测试和实现 RepositoryM,然后可以测试和实现ClassA

...如此往复。

使用mocks允许您在不实现任何内容之前开始编写测试。您所需要的只是接口。

使用mocking框架可以大大加快测试构建速度。

Mocking/stubbing有辅助好处--其中一个好处是强制编程到抽象而不是实现。


Mocking在测试中隔离一个类时非常有效;你不需要TDD来进行Mocking。 - hvgotcodes
当然可以;我的回答只涉及到TDD的一部分,而在这一部分中,我说模拟非常重要,因为它允许隔离。我的意思是这样可以补充你提供的信息。 - Jay

2
你们认为使用mock比不使用mock更好吗?
骑摩托车比开汽车更好吗?这要看你想达到什么目的 :).
为什么使用mock?
Mock与基于状态的测试相比:虽然我通常喜欢基于状态的测试,因为它感觉更加坚实/直接,但通常使用mock是验证代码单元是否正确执行其角色的唯一方法。为什么?当以“告诉,不要询问”的原则设计时,类通常不会公开足够的数据来验证您的期望,因此验证其正常工作的唯一方法是检查其行为/与其他协作者的交互。一个很好的例子是一个在订单完成时发送电子邮件的类——该类不会有“发送电子邮件数量”的属性或任何类似的东西,因此您需要检查是否进行了适当的方法调用。Mocks在交互方面设置了期望。
虽然您可以手动编写测试双类来测试交互(例如创建实现所需接口的类型,然后将方法调用信息推入列表,然后根据存储的状态进行断言),但模拟框架通过允许我们仅填充实际关心的部分来加速该过程。
“我在生产代码中应该使用Mock吗?”
如果您指的是使用“可以替换为真实对象并以合理方式运行的'虚假'类型”,那么是的--我经常使用'虚假'类型,例如内存字典来替代数据库连接等。它们可以作为非生产代码中有用的临时解决方案。同样,如果您针对接口编程,则可以创建一个具有存根功能的应用程序工作骨架。这有助于快速制定完整的编程结构,而无需专注于细节。一旦可用真正的实现,就可以进行替换(尽管如果没有集成测试支持,可能会出现一些集成错误)。
如果你所说的“mocking”是指在生产代码中使用模拟框架,那么不,我不建议这样做,我会手写虚拟实现并避免依赖,这样更容易推理和调试。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接