【问题标题】:RhinoMock vs. TypeMock vs. NUnit's Mocking?RhinoMock vs. TypeMock vs. NUnit 的 Mocking?
【发布时间】:2010-11-25 15:21:21
【问题描述】:

我刚开始做测试驱动开发,我想知道 RhinoMock、TypeMock 和 NUnit 的内置模拟之间的主要区别?

任何信息将不胜感激!

【问题讨论】:

    标签: unit-testing nunit mocking rhino-mocks typemock


    【解决方案1】:

    TypeMock 是一种商业产品(意味着您必须为此付费),但允许您模拟具体对象 - 不像 RhinoMocks/NUnit/MoQ 只能模拟接口/抽象类。它是如何实现这一点的,这是一种边缘黑魔法,但它使用 CLR 做了一些非常聪明的事情。

    当您在项目中使用不使用很多接口的库时,这可能特别有用。因此,例如,您可以使用 TypeMock 模拟 LINQtoSQL 数据上下文或 Sharepoint 对象。但是,如果您使用的是 TypeMock,这不是您应用程序设计不佳的借口

    据我所知,除了细微的语法差异外,大多数模拟框架都已脱离旧的记录/播放模型。通常,您通过使用 Fluent Interface 编写期望来设置模拟。

    就我个人而言,我只使用了 MoQ 并且我

    【讨论】:

    • 静态和密封类并不总是一个糟糕的设计,但使用 RhinoMocks/NUnit/MoQ 模拟它们是不可能的。您是否只是因为您的工具不支持而放弃了整个功能集?
    • @HeavyWave 他们不是总是糟糕的设计,但如果你发现自己处于想要/需要模拟它们的情况,那么它可能是糟糕的设计 这一次
    • 啊,不。我有很多不应该是用户可扩展的类,所以它们不是虚拟/密封的。你猜怎么着——我经常需要模拟其中一个类,以便在其中显示该类的特定行为。解封它们并不好 - 框架“依赖”它们不被扩展。
    • @TomTom - 这会很丑陋,但可以将编译条件放在这些类的声明周围,以允许可以进行单元测试但没有密封类的构建,也可以创建具有密封类的构建密封类。
    • @jpierson 是的,这完全违背了单元测试的精神,它甚至都不好笑;)
    【解决方案2】:

    Roy Osherove 的名为 TDD - Understanding Mock Objects 的视频对于了解不同模拟库的差异非常有帮助。他没有详细介绍每个方面,但足以让您理解。我希望这有帮助。 Roy 也是 TypeMock 的首席架构师,是单元测试领域非常有影响力的人物。对于想要学习如何使用模拟并了解可用库的人,我再怎么推荐这个视频都不为过。

    TypeMock 和开源库的主要区别在于 TypeMock 使用 Microsoft 提供的 Profiler API 而不是dynamic proxy。这允许 TypeMock 模拟具体的类和静态方法。如果您不确定分析器是什么,它与 JetBrain 的 dotTrace 和 RedGate 的 Ants .Net 分析器等工具使用的 API 相同。 TypeMock 只是以不同的方式使用 API 来伪造(模拟)你告诉它的内容。

    @RichardOD,感谢您的提醒,他的书“The Art of Unit Testing”在视频没有的地方进行了更详细的介绍。我拥有这本书,内容丰富。

    【讨论】:

    • 他也有一本很棒的书。
    【解决方案3】:
    • Rhino.Mocks 是由业界最多产的开发人员之一不断开发和改进的开源框架。它已经存在了一段时间,因此支持很多不同的模拟范式。因此,从某种意义上说,您可能会找到有关“旧”做事方式的教程,因此学习起来可能会有些困难。这里有一个提示,SetUpResultFor()Expect.Call() 是旧的做事方式。新方法是 mockObject.AssertWasCalled()

    我没有与其他人有过任何亲身经历,但是......

    • MOQ 是一个开源的、不断开发和改进的框架,由行业中产量较低的开发人员之一(与 Ayende 相比)。它较新,因此缺少 Rhino.Mocks 所具有的一些功能。这通常不是问题,因为这些功能往往在 Rhino 中有些被弃用。我听说正因为如此,它更容易学习(顺便说一句,模拟框架并不难学)。
    • 就模拟而言,NUnit Mocks 非常古怪。它不支持当前首选的 Arrange-Act-Assert 语法,而是依赖于 Expect-Verify(记录/重播)。它还依赖字符串而不是 lambdas 来识别方法和属性名称。这使得它对重构有很大的抵抗力。这是一个严重的问题。我不会推荐它。
    • TypeMock Isoler 是来自一家公司(归?)Roy Osherove 的核心付费模拟框架,他知道自己的测试,但对于如何应用它也有一些轻微的争议性意见。就它所能做的而言,它真的很激烈——深入到底层并修改 CLR 对象的工作方式。然而,TypeMock 背后的理念并不是真正的 100% TDD。 TDD 的部分好处是,通过接受 Mocking 框架的限制,您将设计出更好的代码。 TypeMock 打破了这些限制。据我所知,它主要由那些试图获取他们无法控制被测代码的人使用。

    【讨论】:

    • 反对票不是来自我,但我不同意“接受 Mocking 框架的限制,您将设计更好的代码”。我是说,你是认真的吗?假设我想遵循“信息隐藏”的原则,完全封装一个非公共的帮助类。那些有限的模拟工具不允许我这样做!公开该帮助程序类并减少封装如何导致更好的代码?
    • 我并不是说像 TypeMock 这样的巨头没有它的位置。我的意思是,如果您可以完全控制您的代码并遵循良好实践,您将不需要任何高级 Mocking 功能。证据?在 Jermey Miller、Rob Connery、Scott Bellware 等众多强大的开发者中,除了 Rhino 和 MoQ 之外,我还没有听说过他们使用任何东西。 Ayende 是个聪明人(可能是最聪明的人)——如果他觉得自己需要模拟静力学,他会这么做的。至于 DI 是主要原则 - 这是 SOLID 中的 D!
    • 我阅读了所有这些文章,我确实理解它们。您对用于 DIP 的 DI、Service Locator 和 Plugin 是正确的;我从来没有说过别的。但正如我之前解释的那样,这些概念是不同的。 Bob Martin 起源于 DIP,但不是 DI,它是由 Martin Fowler 在martinfowler.com/articles/injection.html 中创造的。 Martin 认为 DIP 对 OO 的重要性是错误的。这不仅仅是我的观点,正如 Fowler、Josh Bloch、GoF、Andrew Hunt、Steve McConnel、Brian Kernighan 等作者关于 OO 的其他知名书籍和文章中没有提及 DIP 所证明的那样。
    • Ayende 没问题,我只是好奇。我很高兴看到你不只是盲目地跟随别人。但是您应该对模拟工具中这些限制的后果更加开放。当开发人员为了单元测试而创建单独的接口或声明虚拟方法时,他通过增加不必要的、毫无意义的复杂性对项目造成了损害。一个好的模拟工具不应该强迫它。试图“强迫”开发人员进入良好的 OO 根本行不通,因为坏人总是会规避它。
    • 哇,以文明方式结束的互联网争论?检查天空!这是末日吗?我会跟进另一个线程,但由于我很好奇,所以我会问一个简短的问题。 TDD的过程也对开发施加了一定的限制。我会断言这些限制是关于 TDD 的事情之一,它可以帮助人们学习如何创建好的设计。你同意吗?如果是这样,那么您同意限制可以帮助学习 - 您是否认为 Rhino Mocks 应用的限制是错误的?
    【解决方案4】:

    我一直在使用 TypeMock,发现它是一个非常强大的工具,可以提高我的单元测试的覆盖率。这是因为我使用 SharePoint,只有 TypeMock 可以让我模拟 SharePoint 类 - 因为它们是具体类而不是接口。

    RhinoMock、Moq、NUIt 等无法模拟 SharePoint 类,因为(我相信)它们需要模拟对象的接口,而不是能够模拟实际的具体类。

    如果您的代码确实使用了很多接口,并且您不需要模拟具体类,那么 TypeMock 有点贵,但就您获得的功能而言,这是值得的。

    【讨论】:

    • 您始终可以将 SharePoint 类包装在您自己的简单包装类中,该包装类只是转发调用。然后可以通过接口访问包装类并对其进行模拟。包装类也可以作为一个外观来简化您与 3rdparty 类的交互。这里不需要 TypeMock。
    • 现实检查:时间就是金钱。是的,我可以再写 100 个类来解决 a 的限制。我也可以得到一个工具。更便宜。更少的代码。
    猜你喜欢
    • 2011-08-10
    • 2011-02-07
    • 2011-03-20
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    • 2011-10-10
    • 2017-09-03
    相关资源
    最近更新 更多