许多人在编写单元测试时使用 Mock Objects。什么是模拟对象?为什么我永远需要一个?我需要一个模拟对象框架吗?
9 回答
对象模拟用于将依赖项排除在单元测试之外。有时你会有一个像“SelectPerson”这样的测试,它会从数据库中选择一个人并返回一个 Person 对象。
为此,您通常需要对数据库的依赖,但是通过对象模拟,您可以使用模拟框架模拟与数据库的交互,因此它可能会返回一个看起来像从数据库返回的数据集,然后您可以测试您的代码以确保它处理将数据集转换为人员对象,而不是使用它来测试与数据库的连接是否存在。
有几个人已经回答了“什么”,但这里有几个我能想到的快速“为什么”:
表现
因为单元测试应该很快,所以如果使用模拟对象来测试与网络、数据库或其他时间密集型资源交互的组件,则无需付出代价。节省的钱很快就会增加。
合作
如果您正在编写一段需要与其他人的代码交互的封装良好的代码(尚未编写,或者正在并行开发 - 一个常见的场景),您可以使用模拟对象来练习您的代码一次接口已约定。否则,在其他组件完成之前,您的代码可能不会开始测试。
模拟对象可以让您测试您正在编写的内容,以及访问资源(磁盘、网络服务等)等抽象细节。然后模拟让你假装是那个外部资源,或类或其他什么。
您实际上并不需要一个模拟对象框架,只需扩展您不想在测试中担心的功能的类,并确保您正在测试的类可以使用您的模拟而不是真实的东西(将其传入通过构造函数或设置器或其他东西。
练习将显示模拟何时有用,何时无用。
编辑:模拟资源特别重要,因此您不必在测试期间依赖它们存在,并且您可以模拟它们如何存在以及它们响应的细节(例如模拟 FileNotFoundException 或缺少的 web 服务,或网络服务的各种可能的返回值)......所有这些都没有涉及缓慢的访问时间(模拟将证明比在测试中访问此类资源要快得多)。
我需要一个模拟对象框架吗?
当然不是。有时,手动编写模拟可能非常乏味。但对于简单的事情,它一点也不差。将Last Responsible Moment的原则应用于 mocking 框架,只有当你向自己证明手写 mock 麻烦多于其价值时,你才应该从手写 mock 切换到框架。
如果您刚开始使用模拟,直接跳入框架将使您的学习曲线至少翻倍(您可以翻倍曲线吗?)。当您在几个项目中手动编写模拟时,模拟框架会更有意义。
对象模拟是一种从接口、抽象类或具有虚拟方法的类创建“虚拟”或模拟对象的方法。它允许您将其中之一包装在您自己的定义中以进行测试。它对于创建一个依赖于您正在测试的某个代码块的对象很有用。
我喜欢使用的一个流行的叫做Moq,但还有很多其他的,比如 RhinoMock 和许多我不知道的。
它允许您测试项目的一个部分如何与其他部分交互,而无需构建整个项目并可能遗漏重要部分。
编辑:来自维基百科的好例子:它允许您预先测试代码,就像汽车设计师使用碰撞测试假人来测试汽车在事故中的行为一样。
另一个用途是它可以让您针对尚未构建的系统的其他部分进行测试。例如,如果您的类依赖于某个其他类,而该类是其他人正在开发的功能的一部分,您可以只要求一个基本完整的接口,对接口进行编程,然后按照您期望它们工作的方式模拟细节。然后,确保您对接口的假设是正确的(无论是在开发过程中,还是在功能完成后)。
模拟框架是否有用部分取决于您编写的代码的语言。使用静态语言,您需要付出额外的努力才能诱使编译器接受您的模拟对象作为真实对象的替代品。在 Python、Ruby 或 Javascript 等动态类型语言中,您通常可以将方法附加到任意对象或类上并将其作为参数传递——因此框架增加的价值要少得多。
.net 单元测试的 2 个推荐模拟框架是 Typemock Isolator 和 Rhino Mock。
在下面的链接中,您可以看到 Typemock 关于为什么需要一个模拟框架进行单元测试的解释。