C# 为什么我应该使用模拟框架而不是赝品?

C# 为什么我应该使用模拟框架而不是赝品?,c#,unit-testing,C#,Unit Testing,这个问题在这里还有其他一些变体,但请阅读整个问题 通过使用赝品,我们可以查看构造函数以了解类具有何种依赖关系,然后相应地为它们创建赝品 然后,我们通过查看一个方法的契约(方法签名),为它编写一个测试。如果我们不知道如何通过这样做来测试该方法,那么我们是否应该尝试重构该方法(很可能将其分解成更小的部分),而不是查看其内部以确定我们应该如何测试它?换句话说,这样做也给了我们一个质量控制 mock不是一件坏事吗,因为它们要求我们查看要测试的方法的内部?因此,跳过整个“以评论家的身份看待签名” 更新以回

这个问题在这里还有其他一些变体,但请阅读整个问题

通过使用赝品,我们可以查看构造函数以了解类具有何种依赖关系,然后相应地为它们创建赝品

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

mock不是一件坏事吗,因为它们要求我们查看要测试的方法的内部?因此,跳过整个“以评论家的身份看待签名”

更新以回答评论

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

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

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


仅仅通过查看合同来测试方法不是更好吗?毕竟,当我们使用该方法时,我们只会在使用它时查看合同。因此,it合同易于遵循和理解是非常重要的。

我认为它有点不同。让我解释一下我的观点:

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


希望这能帮助你找到答案。

假货只是愚蠢的虚拟物品。模拟使您能够验证单元的控制流是否正确(例如,它使用预期参数调用正确的函数)。这样做通常是测试事物的好方法。例如,
saveProject()
-函数可能希望对要保存的对象调用类似于
saveToProject()
的东西。我认为这样做比把项目保存到一个临时缓冲区要好很多,然后加载它来验证一切都很好(这个测试超出了它的要求),它也验证了<代码> SaveProjProject()/Case>实现(s)是正确的。
至于mock与stub,我通常(并非总是)发现mock提供了更清晰的测试和(可选)对期望的更细粒度控制。尽管mock功能太强大了,它允许您测试一个实现,使您的测试达到更改测试中的实现时结果保持不变的水平,但测试失败。

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

string readDoc(name, fileManager) { return fileManager.Read(name).ToString() }
您可以在这里直接测试返回值,所以存根工作正常

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

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

这是一个灰色区域,我认为存在一些重叠。总的来说,我更喜欢使用模拟对象

我想其中的一些取决于您如何进行代码测试-测试还是先测试代码

如果您遵循一个测试驱动的设计计划,并且对象实现了接口,那么您可以在运行时有效地生成一个模拟对象

每次测试都将被测对象/方法视为一个黑匣子

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

但最重要的是,它允许您拥有运行时代码,该代码将模拟对象用于代码的未写入区域


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

我不确定是否理解您的“假”概念。Mock本质上是假的。你能详细说明一下“而不是深入研究它,找出我们应该如何测试它”吗?我们需要知道里面到底发生了什么来测试它,否则我们就不知道该期待什么,该测试什么。啊,如果我们看马丁·弗劳尔(Martin Flower),那里有假人、赝品、存根和模仿品,它们彼此都不一样。请阅读:mock允许您对断言进行更精细的控制,而存根只为您提供测试所需的数据。您可以设置一个存根来返回X,但是如何知道该方法是否被调用呢?模拟还允许您检查这一事实。一个更通用的术语是测试DOUBLE@Bartosz:阅读我的更新我使用了模拟框架。你失踪了