代码之家  ›  专栏  ›  技术社区  ›  masoud ramezani

什么是嘲笑?

  •  426
  • masoud ramezani  · 技术社区  · 14 年前

    什么是嘲笑?                                                                                                    .

    8 回复  |  直到 6 年前
        1
  •  503
  •   Jakub Vrána    6 年前

    序言:如果你查名词 嘲弄 在字典里你会发现这个词的一个定义是 仿制品 .


    模拟主要用于单元测试。正在测试的对象可能依赖于其他(复杂)对象。要隔离对象的行为,您需要用模拟真实对象行为的模拟来替换其他对象。如果实际对象不适合合并到单元测试中,这是有用的。

    简而言之,模拟就是创建模拟真实对象行为的对象。


    有时你可能想区分 嘲笑 与…相反 留茬 . 关于这个主题可能有些不同,但我对存根的定义是一个“最小”的模拟对象。存根实现了足够的行为以允许被测试对象执行测试。

    模拟类似于存根,但测试还将验证被测对象是否按预期调用了模拟。测试的一部分是验证模型是否正确使用。

    举个例子:通过实现一个简单的内存结构来存储记录,您可以截取一个数据库。然后,被测试对象可以读写记录到数据库存根,以允许它执行测试。这可以测试与数据库无关的对象的某些行为,并且将包含数据库存根,以便让测试运行。

    如果您想验证被测对象是否向数据库写入了一些特定的数据,那么必须模拟数据库。然后,您的测试将包含关于写入数据库模拟的内容的断言。

        2
  •  50
  •   mfaani    6 年前

    其他答案解释了什么是嘲笑。让我带你通过它 例子 . 相信我,其实比你想象的要简单得多。

    它是原始类的一个子类。它还注入了其他数据,因此您可以避免测试注入的部件 集中 测试代码的其余部分。


    假设您正在编写iOS应用程序并进行网络呼叫,您的工作是测试 你的 应用程序。测试/识别网络呼叫是否按预期工作不是您的责任。测试它是另一方(服务器团队)的责任。必须删除此(网络)依赖项,然后继续测试所有有效的代码 围绕 它。

    网络调用可以返回不同的状态代码404、500、200、303等,并带有JSON响应。

    你的应用程序应该是为 全部的 其中(如果出现错误,应用程序应抛出其预期错误)。模拟的方法是创建类似于真实网络响应的“假想”网络响应(比如200个带有JSON文件的代码),然后测试代码。 没有 “进行真正的网络呼叫并等待网络响应”。您手动硬编码/返回各种网络响应的网络响应,并查看您的应用程序是否按预期工作。(你 从未 假设/测试一个有错误数据的200,因为这不是你的责任,你的责任是测试 你的 应用程序正确的200,或者在400,500的情况下,测试应用程序是否抛出正确的错误)

    这种创造假想“与真实相似”的现象被称为嘲弄。

    为了做到这一点,你 不能 使用您的原始代码(您的原始代码没有预先插入的响应,对吗?)你 必须 添加一些东西,注入/插入通常不需要的虚拟数据(或类的一部分)。

    所以你 子类 原始类并添加任何内容(这里是网络httpresponse、数据或在失败的情况下,传递正确的错误字符串httpresponse),然后“测试子类”,即 嘲弄的 班级。
    您不再测试原始类。模拟/子类代表原始类进行测试

    长话短说,嘲弄是为了 简化 限制 您正在测试的内容,也会使您提供类所依赖的内容。在这个例子中,您 避免测试 这个 网络呼叫自己 ,而不是 测试 你的应用是否如你所期望的那样工作 注入输出/响应 __ 嘲笑

    不用说,您将分别测试每个网络响应。


    现在我一直在想的一个问题是:我的API的契约/端点和JSON响应会不断更新。如何编写考虑到这一点的单元测试?

    要详细说明这一点:假设模型需要一个名为 username . 你测试这个,你的测试通过了。 2周后,后端将密钥的名称更改为 id . 你的测试仍然通过。正确的?是不是?

    后端开发人员是否有责任更新模拟。他们是否应该是我们协议的一部分,提供最新的模拟?

    以上问题的答案是:单元测试+作为客户端开发人员的开发过程应该/将会捕获过时的模拟响应。如果你问我怎么做?答案是:

    如果不使用更新的API,我们的实际应用程序将失败(或没有失败,但没有所需的行为),因此如果失败,我们将对开发代码进行更改。这再次导致我们的测试失败……我们必须纠正它。(实际上,如果我们要正确地执行TDD过程,除非我们为该字段编写测试,否则我们不会编写任何代码……并看到它失败,然后为它编写实际的开发代码。

    这意味着后端不必说:嘿,我们更新了模拟……它 最后 通过代码开发/调试发生。因为它是开发过程的一部分!不过,如果后端系统为您提供模拟响应,那么就更容易了。

    我在这方面的全部观点是,想出一些脚本来获取API的更新模拟是低效的。TDD也不是把你100%的精力放在自动完成事情上,而没有任何人类的互动。过程的一部分是 手册 更新JSON并召开简短会议以确保其值是最新的。

    这一部分是由于我们的cocoahead meetup小组的讨论不充分而编写的。


    仅限iOS开发者:

    嘲笑的一个很好的例子是 Practical Protocol-Oriented talk by Natasha Muraschev 跳到18:30分。

    我真的很喜欢这段文字:

    因为这是测试…我们确实想确保 get 功能 来自 Gettable 被称为, 因为它可以返回 理论上可以从任何地方分配一系列食物 . 我们 需要确保它被调用;

        3
  •  28
  •   David Hall    8 年前

    网上有很多关于模仿的答案和好文章。马丁福勒的帖子是你可能想开始找的地方 Mocks Aren't Stubs 在那里他讨论了很多嘲笑的想法。

    在一个段落中,mocking是一种特殊的技术,它允许在不依赖依赖依赖于依赖性的情况下对代码单元进行测试。一般来说,模拟与其他方法的区别在于,用于替换代码依赖关系的模拟对象将允许设置期望值——模拟对象将知道代码如何调用它以及如何响应。


    你最初的问题提到了typemock,所以我把我的答案留在下面:

    typemock是 commercial mocking framework .

    它提供了免费模拟框架的所有功能,如Rhinomocks和MoQ,以及一些更强大的选项。

    不管你是否需要typemock都是有争议的——你可以用免费的mocking库做你想要做的大多数mocking,许多人认为typemock提供的功能通常会让你远离封装良好的设计。

    正如另一个答案所述,“type mocking”实际上不是一个定义的概念,但可以理解为typemock提供的模拟类型,使用clr探查器在运行时截获.net调用,从而提供更大的伪造对象的能力(而不是需要接口或virtu等需求)所有方法)。

        4
  •  7
  •   Community c0D3l0g1c    7 年前

    mock是一种方法/对象,它以受控方式模拟实际方法/对象的行为。模拟对象用于单元测试。

    测试中的方法通常调用其他外部服务或其中的方法。这些被称为依赖关系。一旦被嘲笑,依赖关系就按照我们定义的方式工作。

    通过mock控制依赖项,我们可以很容易地测试我们编码的方法的行为。这是单元测试。

    What is the purpose of mock objects?

    Mocks vs stubs

    Unit tests vs Functional tests

        5
  •  5
  •   Brian Rasmussen    14 年前

    模拟类型的目的是切断依赖关系,以便将测试隔离到特定单元。存根是简单的代理,而模拟是可以验证使用情况的代理。模拟框架是帮助您生成存根和模拟的工具。

    编辑 :因为最初的措词提到“打字模拟”,我觉得这与打字模拟有关。根据我的经验,一般的说法就是“嘲弄”。请随意忽略typemock上的以下信息。

    typemock-isolator与大多数其他mocking框架的不同之处在于,它可以动态地修改IL。这允许它模拟大多数其他框架无法模拟的类型和实例。要用其他框架模拟这些类型/实例,您必须提供自己的抽象并模拟这些抽象。

    typemock以牺牲干净的运行时环境为代价提供了极大的灵活性。作为typemock实现结果方式的副作用,在使用typemock时有时会得到非常奇怪的结果。

        6
  •  3
  •   Oded    14 年前

    我认为使用typemock隔离器模拟框架将是typemock。

    它是一个生成用于单元测试的模拟的工具,而不需要在考虑IOC的情况下编写代码。

        7
  •  2
  •   Mogsdad    7 年前

    模拟正在生成模拟测试的真实对象行为的伪对象。

        8
  •  1
  •   foobar8675    10 年前

    如果模拟涉及到一个网络请求,另一种选择是使用一个真正的测试服务器。您可以使用此服务为测试生成请求和响应。 http://testerurl.com/