Closed. This question is off-topic。它当前不接受答案。
想改善这个问题吗? Update the question,所以它是on-topic,用于堆栈溢出。
7年前关闭。
Improve this question
尽管有很多资源,即使在SO上也有,但是在这些Q / A中只有两个术语被相互比较。
因此,简而言之,它们各自是什么?以及它们如何相互联系?还是根本不?
很容易说出
在这一点上,我们应该得出一个结论,即
快速浏览TDD
存根是存根,在幼稚的实现中也可以用常量替换:
这实质上是模拟框架对存根所做的工作-指示它们返回可配置/显式值。老派的手工存根通常就是这样做的-返回恒定值。
显然,这样的代码没有多大意义,但是曾经做过TDD的任何人肯定在类开发的早期就看到了许多这样的幼稚实现。 TDD产生的迭代开发通常将有助于识别类的依赖项的角色。
如今的存根,模拟和假货
在这篇文章的开头,我提到伪造只是一个通用术语。鉴于模拟也可以用作存根(特别是在涉及现代模拟框架时),为避免混淆,将此类对象称为伪造是个好主意。如今,您可以看到这种趋势在增长-原始的模拟-存根区分已逐渐成为历史,并且使用了更多通用名称。例如:
FakeItEasy使用假冒
NSubstitute使用替代
Moq使用模拟(名称很旧,但是无论是存根还是模拟都没有明显的区别)
参考资料,进一步阅读
Martin Fowler的Mocks aren't stubs-您可以看到这篇文章实际上在任何存根/模拟问题下都被链接了,这是有原因的
Mark Seemann的Exploring The Continuum Of Test Doubles-所有令人困惑的单元测试术语的概述(如果您认为模拟,假冒和存根就足够了,那么您可能应该知道还存在* dummy **,spy,double和not)
xunitpatterns.com-巨大的单元测试模式书的支持网站,xUnit Test Patterns: Refactoring Test Code,作者Gerard Meszaros
Roa Osherove的Art of Unit Testing-出色的单元测试入门书(“模拟可以使测试失败,不存根”是Roy的话,不是我的)
想改善这个问题吗? Update the question,所以它是on-topic,用于堆栈溢出。
7年前关闭。
Improve this question
尽管有很多资源,即使在SO上也有,但是在这些Q / A中只有两个术语被相互比较。
因此,简而言之,它们各自是什么?以及它们如何相互联系?还是根本不?
最佳答案
模拟和存根之间的区别非常简单-模拟可以使测试失败,而存根则不能。这就是全部。此外,您可以将存根视为提供价值的东西。如今,假冒对他们俩来说只是一个通用术语(稍后会详细介绍)。
例
让我们考虑一种情况,在这种情况下,您必须构建一个通过通信协议发送程序包的服务(确切的细节无关紧要)。您只需提供带有包装代码的服务,其余的工作即可完成。给定以下代码段,您可以确定潜在的单元测试中哪个依赖项是存根,哪个模拟吗?
public class DistributionService
{
public double SendPackage(string packageCode)
{
var contents = this.packageService.GetPackageContents(packageCode);
if (contents == null)
{
throw new InvalidOperationException(
"Attempt to send non-exisiting package");
}
var package = this.packageBuilder.Build(contents);
this.packageDistributor.Send(package);
}
}
很容易说出
packageBuilder
只是提供了价值,并且没有任何可能使任何测试失败的方法。那是一个存根。即使看起来似乎更模糊,packageService
也是存根。它提供了一个值(从存根的角度来看,我们与该值无关)。当然,稍后我们将使用该值来测试是否引发了异常,但是它仍然在我们的控制之内(例如,我们确切告诉存根该做什么而忽略了它-它对测试没有任何进一步的影响)。packageDistributor
变得不同。即使它提供任何值,也不会消耗。但是,对Send
的调用似乎是我们实现中非常重要的部分,我们很可能希望验证它是否被调用。在这一点上,我们应该得出一个结论,即
packageDistributor
是一个模拟。我们将有一个专用的单元测试,断言Send
方法已被调用,并且由于某些原因而不被调用-我们想知道这一点,因为它是整个过程的重要组成部分。其他依赖项是存根,因为它们所做的只是为其他可能更相关的代码段提供值。快速浏览TDD
存根是存根,在幼稚的实现中也可以用常量替换:
var contents = "Important package";
var package = "<package>Important package</package>";
this.packageDistributor.Send(package);
这实质上是模拟框架对存根所做的工作-指示它们返回可配置/显式值。老派的手工存根通常就是这样做的-返回恒定值。
显然,这样的代码没有多大意义,但是曾经做过TDD的任何人肯定在类开发的早期就看到了许多这样的幼稚实现。 TDD产生的迭代开发通常将有助于识别类的依赖项的角色。
如今的存根,模拟和假货
在这篇文章的开头,我提到伪造只是一个通用术语。鉴于模拟也可以用作存根(特别是在涉及现代模拟框架时),为避免混淆,将此类对象称为伪造是个好主意。如今,您可以看到这种趋势在增长-原始的模拟-存根区分已逐渐成为历史,并且使用了更多通用名称。例如:
FakeItEasy使用假冒
NSubstitute使用替代
Moq使用模拟(名称很旧,但是无论是存根还是模拟都没有明显的区别)
参考资料,进一步阅读
Martin Fowler的Mocks aren't stubs-您可以看到这篇文章实际上在任何存根/模拟问题下都被链接了,这是有原因的
Mark Seemann的Exploring The Continuum Of Test Doubles-所有令人困惑的单元测试术语的概述(如果您认为模拟,假冒和存根就足够了,那么您可能应该知道还存在* dummy **,spy,double和not)
xunitpatterns.com-巨大的单元测试模式书的支持网站,xUnit Test Patterns: Refactoring Test Code,作者Gerard Meszaros
Roa Osherove的Art of Unit Testing-出色的单元测试入门书(“模拟可以使测试失败,不存根”是Roy的话,不是我的)
07-26 09:25