我如何知道何时使用基于状态的测试与模拟测试?

时间:2020-03-05 18:50:58  来源:igfitidea点击:

与使用模拟对象相比,哪种方案,应用程序/系统的区域等最适合基于"经典"状态的测试?

解决方案

回答

我们应该使用模拟作为依赖项。我不认为这是非此即彼的;通常,我们将为依赖项创建模拟,对它们设置期望值(无论是调用还是状态),然后运行被测单元。然后,我们将检查其状态,并随后验证对模拟的期望。

回答

使用模拟对象并不意味着我们不进行基于状态的测试。

回答

这是一个风格问题。Mockist与Classic TDDers。
就个人而言。我会尽可能地测试真实的类。尽量降低对Mocks的影响;只是去耦诸如IO(文件系统,数据库连接,网络),第三方组件等之类的东西,而这些东西缓慢/难以测试。

回答

作为经验丰富的TDD'er,这是其他开发人员经常问到的问题。对我来说,陷入模拟主义者与古典主义者的辩论是错误的,因为这样的讨论是误导性的。基于状态和基于行为的单元测试是我们工具箱中的两个不同工具,因此没有理由将它们相互排斥。

当我们要在与对象的外部接口通信之后查询对象的内部属性时,基于状态的单元测试非常适合。如果一个或者多个协作者涉及到对其他对象的潜在昂贵调用,则一定要保留这些调用,而根本不理会协作者。

当我们要考虑单元测试的"方式"并专注于揭示对象之间的关系时,基于行为的单元测试是一个好主意,这与基于状态的单元测试的传统"什么"问题相反。如果我们想断言以某种方式和/或者顺序使用了协作者,请使用提供断言的模拟存根。

我建议我们将重点放在标准单元测试实践上,以尽可能少地使用生产代码,并且每个测试只有一个断言。这将迫使我们考虑"我想在此测试中确切地行使和主张什么?",并且对该问题的答案将选择正确的单元测试工具。

回答

我将从TDD / BDD的角度来解决这个问题,因为测试正在推动设计。

首先,它取决于我们购买哪种设计风格,因为请记住,这首先是关于设计的。正如马丁·福勒(Martin Fowler)在这篇出色的文章中所讨论的,《无聊的存根》有两种学派,它们确实产生了不同类型的设计。

如果我们想接受模拟方法,那么我强烈建议我们先查看模拟对象网站及其文章模拟角色,而不是对象。他们也有一本书问世。

事实是,即使我们确实认为模拟优先设计风格不适合我们,或者我们不想直接在应用程序中进行设计(例如,在测试域/服务层时也不希望这样做),我们仍然会想要使用测试双打。 xUnit Test Patterns解释了不同类型的测试双打及其用途。

我个人从不模拟域类,因此也从不模拟实体/值对象。但是,最近我一直在尝试模拟对象样式方法,它确实改变了我的设计,而且我发现工作样式很舒适。在MVC应用程序中以这种方式工作时,我可能会先进行自动验收测试,然后编写一个控制器测试,以模拟掉任何非域对象(例如存储库/服务),然后继续进行测试这些存储库/服务再次模拟了它们的依赖关系。当我到达一个没有麻烦的依赖项(例如域实体/值对象)的类时,我就停了下来。我可以继续对特定的角色接口进行测试,然后由我的领域类实现这些接口,这是模拟对象会推荐的,但是我目前在这种方法中没有看到很多价值。

显然,值得添加的一点是,测试设计在这里很重要,但是请记住,尽管90%的IoC /模拟/ DIP示例显示了接口-实现对(ICustomerRepository / CustomerRepository),但寻找角色接口还是有很多价值的。

回答

在使用服务时,无论是我自己的还是第三方的,我都理所当然地设计了接口,因此我倾向于关注那里的交互。这鼓励我设计最少的接口。

我会检查状态值是否集中在值对象上,就像简单的计算,查找等一样。

下次我们发现自己设计通常遵循模型/视图/控制器或者演示者的内容时,我强烈建议我们尝试使用模型和视图的界面使用Presenter First方法(Google it)。这将使我们对如何有效使用存根/存折有很好的感觉。