What is Mocking?
什么是嘲笑?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????.
序言:如果你查字典里的名词模拟,你会发现这个词的一个定义是模仿的。
模拟主要用于单元测试。正在测试的对象可能依赖于其他(复杂)对象。要隔离对象的行为,您需要用模拟真实对象行为的模拟来替换其他对象。如果实际对象不适合合并到单元测试中,这是有用的。
简而言之,模拟就是创建模拟真实对象行为的对象。
有时,你可能想区分嘲笑和存根。关于这个主题可能有些不同,但我对存根的定义是一个"最小"的模拟对象。存根实现了足够的行为以允许被测试对象执行测试。
模拟类似于存根,但测试还将验证被测对象是否按预期调用了模拟。测试的一部分是验证模型是否正确使用。
举个例子:通过实现一个简单的内存结构来存储记录,您可以截取一个数据库。然后,被测试对象可以读写记录到数据库存根,以允许它执行测试。这可以测试与数据库无关的对象的某些行为,并且将包含数据库存根,以便让测试运行。
如果您想验证被测对象是否向数据库写入了一些特定的数据,那么必须模拟数据库。然后,您的测试将包含关于写入数据库模拟的内容的断言。
其他答案解释了什么是嘲笑。让我用一个例子引导您完成它。相信我,其实比你想象的要简单得多。好的。
它是原始类的一个子类。它注入了其他数据,因此您可以避免测试注入的部分,而只关注测试代码的其余部分。好的。
假设您正在编写一个iOS应用程序并进行网络呼叫,您的工作就是测试您的应用程序。测试/识别网络呼叫是否按预期工作不是您的责任。测试它是另一方(服务器团队)的责任。必须删除此(网络)依赖项,然后继续测试围绕它工作的所有代码。好的。
网络调用可以返回不同的状态代码404、500、200、303等,并带有JSON响应。好的。
您的应用程序应该可以为所有这些应用程序工作(如果出现错误,您的应用程序应该抛出其预期的错误)。模拟的方法是创建"假想的类似于真实的"网络响应(比如一个带有JSON文件的200代码),然后在不进行"进行真实的网络调用并等待网络响应"的情况下测试代码。您手动硬编码/返回各种网络响应的网络响应,并查看您的应用程序是否按预期工作。(您从不假设/测试一个有错误数据的200,因为这不是您的责任,您的责任是用正确的200测试您的应用,或者如果是一个400,500,您测试您的应用是否抛出了正确的错误)好的。
这种创造假想类似于真实的被称为嘲弄。好的。
为了做到这一点,您不能使用原始代码(您的原始代码没有预先插入的响应,对吗?)。必须添加一些东西,插入/插入通常不需要的虚拟数据(或类的一部分)。好的。
因此,您对原始类进行子类化,并添加您需要的任何内容(这里是网络httpResponse、数据,或者在失败的情况下,传递正确的errorString、httpResponse),然后"测试子类"(即模拟类)。您不再测试原始类。模拟/子类代表原始类进行测试好的。 长话短说,模拟是为了简化和限制您正在测试的内容,并且使您能够提供类所依赖的内容。在这个例子中,您避免测试网络调用本身,而是通过模拟类来测试您的应用程序在注入的输出/响应中是否如您所期望的那样工作。好的。 不用说,您单独测试每个网络响应。好的。 现在我一直在想的一个问题是:我的API的契约/端点和JSON响应会不断更新。如何编写考虑到这一点的单元测试?好的。 要详细说明这一点:假设模型需要一个名为 后端开发人员是否有责任更新模拟。他们是否应该是我们协议的一部分,提供最新的模拟?好的。 以上问题的答案是:单元测试+作为客户端开发人员的开发过程应该/将会捕获过时的模拟响应。如果你问我怎么做?答案是:好的。 如果不使用更新的API,我们的实际应用程序将失败(或没有失败,但没有所需的行为),因此如果失败,我们将对开发代码进行更改。这又导致我们的测试失败……我们必须纠正它。(实际上,如果我们要正确地执行TDD过程,我们将不会编写关于该字段的任何代码,除非我们为其编写测试……并看到它失败,然后为其编写实际的开发代码。)好的。 这意味着后端不必说:"嘿,我们更新了模拟"…它最终会通过代码开发/调试发生。???因为这都是开发过程的一部分!不过,如果后端系统为您提供模拟响应,那么就更容易了。好的。 我的观点是(如果你不能自动获得更新的模拟API响应),需要一些人工交互,比如手动更新JSON,并召开简短的会议以确保它们的值是最新的,这将成为你过程的一部分。好的。 本节的编写归功于我们的Cocoahead Meetup Group中的一个松散讨论好的。 仅限iOS开发者:好的。 模拟的一个很好的例子是Natasha Muraschev的这个面向协议的实用对话,跳到第18:30分钟。好的。 我真的很喜欢这段文字:好的。
Because this is testing...we do want to make sure that the Ok. 好啊。 网上有很多关于模仿的答案和好文章。你可能想开始找的一个地方是马丁·福勒的帖子《嘲弄不是存根》,他讨论了很多嘲弄的想法。 在一个段落中,mocking是一种特殊的技术,它允许在不依赖依赖依赖于依赖性的情况下对代码单元进行测试。一般来说,模拟与其他方法的区别在于,用于替换代码依赖关系的模拟对象将允许设置期望值——模拟对象将知道代码如何调用它以及如何响应。 你最初的问题提到了typemock,所以我把我的答案留在下面: typemock是商业模拟框架的名称。 它提供了免费模拟框架的所有功能,如Rhinomocks和MoQ,以及一些更强大的选项。 不管你是否需要typemock都是有争议的——你可以用免费的mocking库做你想要做的大多数mocking,许多人认为typemock提供的功能通常会让你远离封装良好的设计。 正如另一个答案所述,"type mocking"实际上不是一个定义的概念,但可以理解为typemock提供的模拟类型,使用clr探查器在运行时拦截.net调用,从而提供更大的伪造对象的能力(而不是需要接口或虚拟方法等要求)。 mock是一种方法/对象,它以受控方式模拟实际方法/对象的行为。模拟对象用于单元测试。 测试中的方法通常调用其他外部服务或其中的方法。这些被称为依赖关系。一旦被嘲笑,依赖关系就按照我们定义的方式工作。 通过mock控制依赖项,我们可以很容易地测试我们编码的方法的行为。这是单元测试。 模拟对象的目的是什么? 嘲笑与存根 单元测试与功能测试
from the
could theoretically assign an array of food items from anywhere. We
need to make sure that it is called;
模拟类型的目的是切断依赖关系,以便将测试隔离到特定单元。存根是简单的代理,而模拟是可以验证使用情况的代理。模拟框架是帮助您生成存根和模拟的工具。
编辑:由于最初的措辞提到"类型模仿",我觉得这与类型模仿有关。根据我的经验,一般的说法就是"嘲弄"。请随意忽略typemock上的以下信息。
typemock-isolator与大多数其他mocking框架的不同之处在于,它可以动态地修改IL。这允许它模拟大多数其他框架无法模拟的类型和实例。要用其他框架模拟这些类型/实例,您必须提供自己的抽象并模拟这些抽象。
typemock以牺牲干净的运行时环境为代价提供了极大的灵活性。作为typemock实现结果方式的副作用,在使用typemock时有时会得到非常奇怪的结果。
模拟正在生成模拟测试的真实对象行为的伪对象。
我认为使用typemock隔离器模拟框架将是typemock。
它是一个生成用于单元测试的模拟的工具,而不需要在考虑IOC的情况下编写代码。
如果模拟涉及到一个网络请求,另一种选择是使用一个真正的测试服务器。您可以使用此服务为测试生成请求和响应。http://testerurl.com/