Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 隔离框架(Moq、RhinoMock等)是否会导致测试过度规范?_Unit Testing_Tdd - Fatal编程技术网

Unit testing 隔离框架(Moq、RhinoMock等)是否会导致测试过度规范?

Unit testing 隔离框架(Moq、RhinoMock等)是否会导致测试过度规范?,unit-testing,tdd,Unit Testing,Tdd,在Osherove的巨著《单元测试的艺术》中,测试反模式之一是规格过高,这与测试对象的内部状态基本相同,而不是测试一些预期的输出。根据我的经验,使用隔离框架可能会产生与测试内部行为相同的不必要的副作用,因为人们往往只实现使存根与被测对象交互所必需的行为。现在,如果您的实现稍后发生更改(但契约保持不变),那么您的测试将突然中断,因为您希望从未实现的存根中获得一些数据 那么,你认为应对这一问题的最佳方法是什么 1) 完全实现存根/模拟,这会产生负面的副作用,可能会降低测试的可读性,并且还会指定使测试

在Osherove的巨著《单元测试的艺术》中,测试反模式之一是规格过高,这与测试对象的内部状态基本相同,而不是测试一些预期的输出。根据我的经验,使用隔离框架可能会产生与测试内部行为相同的不必要的副作用,因为人们往往只实现使存根与被测对象交互所必需的行为。现在,如果您的实现稍后发生更改(但契约保持不变),那么您的测试将突然中断,因为您希望从未实现的存根中获得一些数据

那么,你认为应对这一问题的最佳方法是什么

1) 完全实现存根/模拟,这会产生负面的副作用,可能会降低测试的可读性,并且还会指定使测试通过所需的更多内容

2) 喜欢手工的,完全实施的假货


3) 实现存根/伪存根,使您的测试刚好通过,然后处理这可能带来的脆弱性。

我认为您不应该喜欢手动测试,除非您更喜欢测试而不是代码

相反,您有另一个选择-如果您测试的是功能而不是实现,请尽量避免测试私有方法(可以重构)一般来说,编写不那么脆弱的测试,您会发现使用模拟/隔离框架不需要过度指定系统,也不会导致测试变得更加脆弱


简言之,编写脆弱测试可以使用或不使用伪造/模拟,反之亦然

我倾向于使用mock而不是stubbed/fake对象。我发现他们的麻烦少了很多,而且他们在控制测试代码方面做得更好,因为它不会被各种半生不熟的实现搞得乱七八糟。它们也有助于澄清正在测试的内容


另一个优点是,我只需要解决被测试的类需要来自模拟的特定内容的地方。所以我不必在不重要的地方编写代码。至于验证,再一次,我只需要非常受测试者的召唤到我关心的模拟,并考虑测试的重要方面。 我认为,问题总是一样的,尽管它有不同的风格:如果你有一些测试以某种方式覆盖了类的内部,那么你就会破坏覆盖了这个内部代码的测试

有两种方法可以解决这个问题:

  • 您的测试只涵盖a类测试策略的公共契约,这正是因为这个原因而被广泛采用的:只要公共契约保持不变,您就不必更改测试。不幸的是,这不是您在进行测试驱动开发时所拥有的
  • 如果您的测试来自TDD过程,那么它们将定期覆盖非公共代码。这意味着,如果您更改代码,它们将中断。保持同步的唯一方法是将测试与代码一起“修复”。这意味着在开发过程中需要更多的维护。没有简单的解决方法(当然,除了扔掉测试…)

  • 我个人的“出路”是从“代码元素”而不仅仅是代码的角度来思考。代码元素由三部分组成:文档、测试、代码。因此,如果更改元素的一部分,还必须调整其他两部分,否则会留下一个损坏的代码元素

    只需澄清一下,我们在这里使用的语义是相同的:mock和stub都是伪造的,区别在于:一个伪造的,您在:mock上执行验证,一个伪造的,您在:stub上执行验证。此外,过度使用模拟也被视为过度规范。(你是在用模拟测试最终结果状态吗)?啊,不,一点也不正确。模拟对象不是存根/赝品。Fake和Stub是同一事物的不同名称-一个类的显式编码扩展,用于测试它们扩展的类,或者注入到正在测试的其他类中以方便测试。它们作为一个明确编写的类存在于测试代码中。另一方面,mock是由mockito之类的mock框架动态创建的。与存根/赝品相比,仿制品有许多优点,而且不那么脆弱。那么,你和我(以及罗伊·奥舍洛夫)对赝品/仿制品和存根的定义存在分歧:-)似乎其他人也同意我的观点:(看看验证过的答案)我想我看到了误解。如果您需要达到该级别,MF的定义很好。我说的是编码要求。Dummys/Fakes/Stubs(DFSs)需要编写一个额外的类。嘲弄是不行的。这对测试代码产生了根本性的影响,并且在开发人员中造成了很多混乱。我曾看到项目团队将DFSs称为模拟,然后在尝试引入模拟框架时会感到困惑。我不同意的原因是你说要实现mock和stub。对我来说,这表明我没有理解mock是什么。我一直专注于黑盒测试(即测试最终结果,而不是实现),但这并没有改变一个复杂服务可以与多个实例交互以执行一项任务的事实。这再一次意味着你(可能)必须指定很多来测试你的最终结果。当然,您可以重用与您的服务交互的类的实现,但这比进行集成测试更重要。进行复杂的测试可能意味着您试图在一个测试中测试太多的内容—提示是,每个测试有多个断言。另一个解决方案是以与测试相同的方式伪造外部依赖项-假装您不知道内部功能,只是需要输出。我始终使用一个断言pr测试。对不起,如果我的问题不是很正式,但你的建议实际上是我的问题。当你开始假装你的依赖(cre