为什么我要用一个嘲弄的框架,而不是假的

本文关键字:框架 嘲弄 一个 我要 为什么 | 更新日期: 2023-09-27 18:13:50

这个问题在SO有一些其他的变化,但请阅读整个问题。

通过使用fakes,我们可以查看构造函数,看看类有什么样的依赖,然后相应地为它们创建fakes。

然后我们通过查看一个方法的契约(方法签名)来编写测试。如果我们不能弄清楚如何通过这样做来测试方法,我们是否应该尝试重构方法(最有可能将其分解为更小的部分)而不是查看它的内部以确定我们应该如何测试它?换句话说,这样做也给了我们质量控制。

难道mock不是一件坏事吗?因为它们要求我们查看要测试的方法的内部?因此,跳过整个"以评论家的眼光看待签名"。

更新回复评论

然后说是存根(只是一个提供请求对象的虚拟类)。

Moq这样的框架确保使用参数XY来调用Method A。为了能够设置这些检查,需要查看被测试方法的内部。

当焦点从方法签名/契约转移到方法内部并创建检查时,在设置所有这些检查时,重要的事情(方法契约)不是被遗忘了吗?

通过查看合同来测试方法不是更好吗?毕竟,当我们使用该方法时,我们只需要在使用它时查看契约。所以很重要的一点是它的合同要易于遵循和理解。

为什么我要用一个嘲弄的框架,而不是假的

这是一个灰色地带,我认为有一些重叠。总的来说,我更喜欢使用模拟对象。

我想这部分取决于你如何测试代码——先测试还是先写代码?

如果您使用对象实现接口遵循测试驱动的设计计划,那么您可以有效地生成模拟对象。

每个测试都将被测试对象/方法视为一个黑盒。

它使您专注于编写更简单的方法代码,因为您知道您想要的答案。

但最重要的是,它允许您在运行时代码中使用模拟对象来编写代码的未编写区域。

在宏层面上,它还允许在运行时切换代码的主要区域,以使用模拟对象,例如模拟数据访问层,而不是具有实际数据库访问的层。

假货只是愚蠢的假对象。模拟使您能够验证单元的控制流是正确的(例如,它使用预期的参数调用正确的函数)。这样做通常是测试事物的好方法。例如,saveProject()函数可能想要在要保存的对象上调用saveToProject()之类的东西。我认为这样做比将项目保存到临时缓冲区,然后加载它以验证一切正常要好得多(这测试了更多-它还验证了saveToProject()实现是正确的)。

对于模拟和存根,我通常(并非总是)发现模拟提供了更清晰的测试和(可选的)对期望的更细粒度的控制。但是,mock可能太强大了,它允许您测试实现到这样的程度:更改被测实现,结果不变,但测试失败。

通过查看方法/函数签名,您可以只测试输出,提供一些输入(仅能够为您提供所需数据的存根)。虽然这在某些情况下是可以的,但有时您需要测试方法内部发生了什么,您需要测试是否正确地行为

string readDoc(name, fileManager) { return fileManager.Read(name).ToString() }

您可以在这里直接测试返回值,因此存根工作得很好。

void saveDoc(doc, fileManager) { fileManager.Save(doc) }

中,您更希望测试方法Save是否使用正确的参数(doc)被调用。文档内容没有改变,fileManager没有输出任何东西。这是因为被测试的方法依赖于接口提供的一些其他功能。接口就是契约,所以你不仅要测试你的方法是否给出正确的结果。您还可以测试它是否以正确的方式使用了提供的契约。

我觉得有点不同。让我解释一下我的观点:

我使用了一个mock框架。当我尝试测试一个类时,为了确保它能按预期工作,我必须测试所有可能发生的情况。当我的被测试类使用其他类时,我必须确保在某些测试情况下,被使用的类或某个返回值会引发特殊异常,等等……这很难用这些类的实际实现来模拟,所以我必须编写它们的仿制品。但我认为,在我使用假的情况下,测试不那么容易理解。在我的测试中,我使用MOQ-Framework并在我的测试方法中设置了模拟。如果我必须分析我的测试方法,我可以很容易地看到模拟是如何配置的,而不必切换到假的编码来理解测试。