Java 重构时Mockito mock对单元测试的影响
如果我使用注入SUT的对象的mockito mock作为参数,那么在重构过程中,如果代码被重新组织以调用同一mock的另一个非mock方法,会发生什么?我的测试将失败,我必须回去更改我的测试,并为这个新调用设置它们(与重构代码时我希望做的相反) 如果这在重构过程中很常见,那么除了模拟外部资源密集型实体(网络、数据库等)之外,使用模拟还有什么用处呢 我使用mock来模拟对象,因为我的团队似乎喜欢非常深的聚合对象,所以需要花费数小时来设置这些对象Java 重构时Mockito mock对单元测试的影响,java,refactoring,tdd,mockito,Java,Refactoring,Tdd,Mockito,如果我使用注入SUT的对象的mockito mock作为参数,那么在重构过程中,如果代码被重新组织以调用同一mock的另一个非mock方法,会发生什么?我的测试将失败,我必须回去更改我的测试,并为这个新调用设置它们(与重构代码时我希望做的相反) 如果这在重构过程中很常见,那么除了模拟外部资源密集型实体(网络、数据库等)之外,使用模拟还有什么用处呢 我使用mock来模拟对象,因为我的团队似乎喜欢非常深的聚合对象,所以需要花费数小时来设置这些对象 谢谢 我建议你只嘲笑最低限度的需求。Mockito有
谢谢 我建议你只嘲笑最低限度的需求。Mockito有很多工具可以做到这一点(间谍、以某种方式调用方法时返回特定数据/模拟的能力等),但最终归结为代码中有可测试的“接缝”。如果您还没有这样做,我建议您阅读Michael Feather的书,以获得许多关于如何做到这一点的建议。您是正确的,重构可能会破坏依赖于模拟的代码。Mockito不知道方法
foo(int-start,int-end)
和foo(int-start)
可以完成同样的事情,如果在重构时在它们之间切换,Mockito模拟很可能会中断。Mockito确实为未订阅的调用提供了合理的默认值,如0、null或空列表;然而,许多重构需要更现实的值
一般来说,我听说当系统正常运行时,测试或测试夹具会失败,这被称为“脆性”
部分原因是mocking框架的选择:Mockito最初是作为EasyMock的分支出现的,在EasyMock中,如果调用太多或太少,EasyMock将默认失败,但Mockito将忽略意外调用,并提供“良好”的默认行为。另一部分取决于您如何使用框架,其中验证不必要的细节(不重要的调用或参数)可能会使模拟变得比必须的更脆弱
Mockito擅长嘲弄事物:
- 外部资源密集型依赖项(或其包装器)
- 接口。这里很少会出错
- 小API表面。如果您的API表面有一个或两个方法,则不太可能捕捉到您所描述的情况
- 还不存在的合作者,即使他们有大的API表面。临时脆性试验可在以后修复
- 非常大的API表面和DSL。想象一下用Mockito实现一个构建器模式!更喜欢使用真实对象,或者编写内存中的伪对象或其他双重测试
- 有状态对象,如数据库和模型对象。假货在这里绝对是更好的选择,如果真的东西不行的话
- 你无法控制的具体类。此时,诸如
选项之类的实现细节开始潜入。这可能是创建由您控制的包装器的一个很好的理由final
- 任何具有现有且经过良好测试的实现的内容。当存在真正的实现时,为什么要经历所有这些麻烦并失去测试保真度
boom()
方法而有所不同
有关测试双重对象(包括模拟、伪造和虚拟对象)及其优缺点的更多详细信息,请参阅Martin Fowler的文章