1
503
序言:如果你查名词 嘲弄 在字典里你会发现这个词的一个定义是 仿制品 . 模拟主要用于单元测试。正在测试的对象可能依赖于其他(复杂)对象。要隔离对象的行为,您需要用模拟真实对象行为的模拟来替换其他对象。如果实际对象不适合合并到单元测试中,这是有用的。 简而言之,模拟就是创建模拟真实对象行为的对象。 有时你可能想区分 嘲笑 与…相反 留茬 . 关于这个主题可能有些不同,但我对存根的定义是一个“最小”的模拟对象。存根实现了足够的行为以允许被测试对象执行测试。 模拟类似于存根,但测试还将验证被测对象是否按预期调用了模拟。测试的一部分是验证模型是否正确使用。 举个例子:通过实现一个简单的内存结构来存储记录,您可以截取一个数据库。然后,被测试对象可以读写记录到数据库存根,以允许它执行测试。这可以测试与数据库无关的对象的某些行为,并且将包含数据库存根,以便让测试运行。 如果您想验证被测对象是否向数据库写入了一些特定的数据,那么必须模拟数据库。然后,您的测试将包含关于写入数据库模拟的内容的断言。 |
2
50
其他答案解释了什么是嘲笑。让我带你通过它 例子 . 相信我,其实比你想象的要简单得多。 铊 它是原始类的一个子类。它还注入了其他数据,因此您可以避免测试注入的部件 集中 测试代码的其余部分。 假设您正在编写iOS应用程序并进行网络呼叫,您的工作是测试 你的 应用程序。测试/识别网络呼叫是否按预期工作不是您的责任。测试它是另一方(服务器团队)的责任。必须删除此(网络)依赖项,然后继续测试所有有效的代码 围绕 它。 网络调用可以返回不同的状态代码404、500、200、303等,并带有JSON响应。 你的应用程序应该是为 全部的 其中(如果出现错误,应用程序应抛出其预期错误)。模拟的方法是创建类似于真实网络响应的“假想”网络响应(比如200个带有JSON文件的代码),然后测试代码。 没有 “进行真正的网络呼叫并等待网络响应”。您手动硬编码/返回各种网络响应的网络响应,并查看您的应用程序是否按预期工作。(你 从未 假设/测试一个有错误数据的200,因为这不是你的责任,你的责任是测试 你的 应用程序正确的200,或者在400,500的情况下,测试应用程序是否抛出正确的错误) 这种创造假想“与真实相似”的现象被称为嘲弄。 为了做到这一点,你 不能 使用您的原始代码(您的原始代码没有预先插入的响应,对吗?)你 必须 添加一些东西,注入/插入通常不需要的虚拟数据(或类的一部分)。
所以你
子类
原始类并添加任何内容(这里是网络httpresponse、数据或在失败的情况下,传递正确的错误字符串httpresponse),然后“测试子类”,即
嘲弄的
班级。
长话短说,嘲弄是为了 简化 和 限制 您正在测试的内容,也会使您提供类所依赖的内容。在这个例子中,您 避免测试 这个 网络呼叫自己 ,而不是 测试 你的应用是否如你所期望的那样工作 注入输出/响应 __ 嘲笑 类 不用说,您将分别测试每个网络响应。 现在我一直在想的一个问题是:我的API的契约/端点和JSON响应会不断更新。如何编写考虑到这一点的单元测试?
要详细说明这一点:假设模型需要一个名为
后端开发人员是否有责任更新模拟。他们是否应该是我们协议的一部分,提供最新的模拟? 以上问题的答案是:单元测试+作为客户端开发人员的开发过程应该/将会捕获过时的模拟响应。如果你问我怎么做?答案是: 如果不使用更新的API,我们的实际应用程序将失败(或没有失败,但没有所需的行为),因此如果失败,我们将对开发代码进行更改。这再次导致我们的测试失败……我们必须纠正它。(实际上,如果我们要正确地执行TDD过程,除非我们为该字段编写测试,否则我们不会编写任何代码……并看到它失败,然后为它编写实际的开发代码。 这意味着后端不必说:嘿,我们更新了模拟……它 最后 通过代码开发/调试发生。因为它是开发过程的一部分!不过,如果后端系统为您提供模拟响应,那么就更容易了。 我在这方面的全部观点是,想出一些脚本来获取API的更新模拟是低效的。TDD也不是把你100%的精力放在自动完成事情上,而没有任何人类的互动。过程的一部分是 手册 更新JSON并召开简短会议以确保其值是最新的。 这一部分是由于我们的cocoahead meetup小组的讨论不充分而编写的。 仅限iOS开发者: 嘲笑的一个很好的例子是 Practical Protocol-Oriented talk by Natasha Muraschev 跳到18:30分。 我真的很喜欢这段文字:
|
3
28
网上有很多关于模仿的答案和好文章。马丁福勒的帖子是你可能想开始找的地方 Mocks Aren't Stubs 在那里他讨论了很多嘲笑的想法。 在一个段落中,mocking是一种特殊的技术,它允许在不依赖依赖依赖于依赖性的情况下对代码单元进行测试。一般来说,模拟与其他方法的区别在于,用于替换代码依赖关系的模拟对象将允许设置期望值——模拟对象将知道代码如何调用它以及如何响应。 你最初的问题提到了typemock,所以我把我的答案留在下面: typemock是 commercial mocking framework . 它提供了免费模拟框架的所有功能,如Rhinomocks和MoQ,以及一些更强大的选项。 不管你是否需要typemock都是有争议的——你可以用免费的mocking库做你想要做的大多数mocking,许多人认为typemock提供的功能通常会让你远离封装良好的设计。 正如另一个答案所述,“type mocking”实际上不是一个定义的概念,但可以理解为typemock提供的模拟类型,使用clr探查器在运行时截获.net调用,从而提供更大的伪造对象的能力(而不是需要接口或virtu等需求)所有方法)。 |
4
7
mock是一种方法/对象,它以受控方式模拟实际方法/对象的行为。模拟对象用于单元测试。 测试中的方法通常调用其他外部服务或其中的方法。这些被称为依赖关系。一旦被嘲笑,依赖关系就按照我们定义的方式工作。 通过mock控制依赖项,我们可以很容易地测试我们编码的方法的行为。这是单元测试。 |
5
5
模拟类型的目的是切断依赖关系,以便将测试隔离到特定单元。存根是简单的代理,而模拟是可以验证使用情况的代理。模拟框架是帮助您生成存根和模拟的工具。 编辑 :因为最初的措词提到“打字模拟”,我觉得这与打字模拟有关。根据我的经验,一般的说法就是“嘲弄”。请随意忽略typemock上的以下信息。 typemock-isolator与大多数其他mocking框架的不同之处在于,它可以动态地修改IL。这允许它模拟大多数其他框架无法模拟的类型和实例。要用其他框架模拟这些类型/实例,您必须提供自己的抽象并模拟这些抽象。 typemock以牺牲干净的运行时环境为代价提供了极大的灵活性。作为typemock实现结果方式的副作用,在使用typemock时有时会得到非常奇怪的结果。 |
6
3
我认为使用typemock隔离器模拟框架将是typemock。 它是一个生成用于单元测试的模拟的工具,而不需要在考虑IOC的情况下编写代码。 |
7
2
模拟正在生成模拟测试的真实对象行为的伪对象。 |
8
1
如果模拟涉及到一个网络请求,另一种选择是使用一个真正的测试服务器。您可以使用此服务为测试生成请求和响应。 http://testerurl.com/ |
Phil Gunning · 使用嵌套函数更改进行模拟测试 2 年前 |
Korr · 如何用Jest模拟组件测试中服务的功能 2 年前 |
Jordan Lee · 在另一个类中使用实例方法作为装饰器 6 年前 |
user2350138 · 为WireMock构建Java项目 6 年前 |
user8584384 · 单元测试不起作用,因为导入的文件作为输入 6 年前 |
Vino · 如何模拟Python类的对象? 6 年前 |
Enrico · .NET核心ASP。带有会话和测试的NET控制器 6 年前 |