假数据比模拟数据更好吗?

53

我偶然发现了这个开源项目Fake It Easy,我必须承认,它看起来非常有趣,但是我还有疑问,FIE伪造对象和Moq模拟对象之间有什么区别?对于特定的用途,哪个更好?

编辑:

这个新框架有什么使它比Moq更好的地方吗?


对于一种完全不同的模拟和存根,请查看微软的Moles框架(http://research.microsoft.com/en-us/projects/moles/)。 Moles允许模拟静态、密封和第三方类。 - softveda
4个回答

110
要明确的是,我创建了FakeItEasy,因此我绝对不会说哪个框架比另一个更好,我可以指出一些差异并激励为什么我创建了FakeItEasy。在功能上,Moq和FakeItEasy之间没有重大区别。
FakeItEasy没有“可验证”或“期望”,但它有断言,这些断言始终明确地陈述在测试的最后,我认为这使得测试更易于阅读和理解。它还帮助初学者避免多个断言(其中他们会对许多调用或模拟对象设置期望)。
我以前使用过Rhino Mocks,并且我很喜欢它,特别是在AAA语法引入后,我更喜欢Moq的流畅API。但我不喜欢Moq中的“模拟对象”,你必须在所有地方使用mock.Object,我更喜欢Rhino-approach中的“自然”模拟。每个实例看起来和感觉像假类型的正常实例。我想要两全其美,也想看看当我完全自由时可以用语法做什么。个人而言,我(显然)认为我创造了一个很好的混合,结合了两个世界的最佳部分,但是当你站在巨人的肩膀上时,这很容易。
正如在这里提到的一样,主要区别之一在于术语,FakeItEasy最初是为了向初学者介绍TDD和模拟而创建的,在Rhino中必须事先担心模拟和存根之间的差异不是很有用。
我把重点放在异常消息上,只需查看异常消息就应该很容易知道测试出了什么问题。
FakeItEasy具有其他框架没有的一些可扩展性功能,但这些功能尚未很好地记录。
FakeItEasy在模拟具有构造函数参数的类方面(希望)更加强大,因为它具有解析虚值以使用的机制。您甚至可以通过在测试项目中实现DummyDefinition(Of T)类来指定自己的虚值定义,这将自动被FakeItEasy选中。
语法是一个明显的区别,哪个更好在很大程度上取决于口味。
我确信现在我忘记了许多其他差异(公平地说,我从未自己在生产中使用过Moq,因此我的知识受限),但我认为这些是最重要的差异。

42
+1 没有什么比作者的帖子更好了 :-) - TheCodeJunkie
1
谢谢@Patrick!非常好的回答,这真的有助于理解项目背后的原因,你应该将这样的内容添加到维基中,供那些已经使用框架并可能有兴趣切换的人使用 :) 顺便问一下,您是否已经使用自己的生产代码进行了FIE测试? - Francisco Noriega
2
是的,我们在我的工作地点大规模地使用FakeItEasy进行自我测试已经有一年多了。 - Patrik Hägne
1
好主意,Francisco。我已经创建了一个新的维基页面。 - Patrik Hägne
FakeItEasy看起来很不错,但为什么要使用“fake”这个术语作为模拟和存根的超集而混淆术语呢?众所周知的作者(Meszaros、Fowler和其他人)已经建立了假对象和存根作为独立的概念。 - Rogério
@Roéiro,我不确定关于那个定义是否有共识,但我认为这确实是最好的超集。向Moq或JMockit提出同样的问题,他们都支持存根,并且我们都知道存根和模拟是不同的概念。 - Patrik Hägne

25

测试中使用的术语可能会有些令人困惑。最好的解释不同概念之间的差异的来源是马丁·福勒(Martin Fowler)的《模拟对象不是存根》(Mocks Aren't Stubs)。简而言之,伪造是一个泛指,可以用来描述存根和模拟对象。


5
任何带有模拟或伪造标签的问题都应该弹出一个“你是否已经阅读了马丁·福勒的文章”的提示窗口 :P - Francisco Noriega
1
该链接确实提供了最好的这些术语定义。 - softveda
这是一篇很棒的文章,但是他需要在格式上再下点功夫。全屏幕长度的纯HTML和未着色的代码真的让阅读变得困难。 - Francisco Noriega
1
+1 - Martin Fowler 简直就是神一般的存在。我从他的网站上学到了很多东西。 - RPM1984
实际上,根据Fowler的文章,“fake”不是指存根和模拟的通用术语,而是第三种“测试替身”(还有第四种“虚拟对象”)。 - Rogério

11
在模拟测试中,术语可能令人困惑,并且有时并不直观。因此,许多人提出了一种更简单的新术语,其中您只有「伪造」、「模拟」和「存根」。
“伪造”是指所有可能类型的测试替身的通用术语,无论它们来自哪里或如何使用。除此之外,“伪造”仅在一个维度上区分:它们是否影响测试结果,或者换句话说,您是否必须为该替身设置返回值,这些返回值在测试执行期间被使用,或者它是一个“静默”对象,仅用于满足某些依赖项。
“存根”则是那个“静默”的对象。
“模拟”则是“积极参与”测试执行的对象。
除此之外,没有进一步的区分-这肯定具有历史上的优点,但现在在很大程度上是违反直觉和学术性的,并且有点混淆了测试驱动开发的重要概念。
关于“Moq”和“FakeItEasy”的比较:从概念角度来看,这两个框架“基本相同”,差异仅在API和术语上...

谁提出了“fake是通用术语”的术语?我知道FakeItEasy库是这样使用的,但就是这样。其他每个作者(Fowler、Meszaros、其他模拟库的创建者)都将“fake”用于一种不同于存根和模拟的测试替身,或者根本不使用此名称(例如,在jMock、EasyMock或Mockito中没有任何名为“fake”的东西)。 - Rogério

-4

从我的角度来看,Fake不会取消Moc的使用。例如,我使用Dev Magic Fake来伪造DAL和Business层,在同一时间内我使用Mock在MVC中处理HTTPContext。

var repoistory = new FakeRepository<ProductTypeForm, VendorForm>();
            repoistory.Save(productTypeForm);
            this.FillDropDown(new FakeRepository<VendorForm>());

在之前的代码中,Dev Magic Fake将保存ProductTypeForm并从Dev Magic Fake检索VendorForm,并将其链接到ProductTypeForm,此保存操作可以是永久性的。
有关Dev Magic Fake的更多信息,请访问CodePlex: http://devmagicfake.codeplex.com 为了测试这种方法,我们必须模拟HTTP上下文。
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();

所以我使用假的和模拟的


1
你似乎更感兴趣于宣传自己的项目,而不是回答问题... - SamuelKDavis

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