全量测试又慢又难以定位错误, 其所需的测试环境的维护成本也很高. 解决方案就是化整为零分别测试. 然而引入新的问题: 测某个"部分"时所需的依赖如何满足. 解决方案是一组被称为"测试替身(Test Double)"的技术. 我们来看一下这里面具体的问题
- 为了能编译通过, 我需要依赖被满足
- 为了能正常运行, 我希望依赖的实现不要出错
- 为了覆盖到真实场景下的用例, 我需要依赖能够模拟真实场景下的行为, 并且我可以在不同的测试用例下指定不同的行为
- 在无法方便的观测系统状态变化而做出断言时, 我希望可以退而求其次, 能够得知SUT(System Under Test)正确的与外部依赖进行了交互.
解决这些问题的技术手段分别叫做Dummy, Stub, Fake, Mock等. 具体介绍可以参见xUnit Test Patterns. 这些技术对SUT的要求就是其能针对接口进行编程, 以避免Test Double的实现技术过于复杂和困难. 而通常这几种Test Double都可以通过手工编写实现某个接口的替身类来完成.
于是这里引入了新的问题: 手工编写替身类太繁琐了, 体力劳动, 重复代码, 大量的测试用例要求大量的替身类. 尤其是测试交互的那些替身类, 要能够记录和断言传入的参数, 调用顺序等. 为解决这些问题需要对替身类进行设计. 而人们发现主流语言Java, C#等提供的语言特性可以动态的生成这些替身类, 简化手工操作和代码量. 于是这类工具被制造出来, 称为mock工具.
换言之, mock工具解决的不是测试中的依赖问题, 而是实现依赖的测试替身手工维护成本太高的问题. (只不过其中对"如何测试交互"那部分的支持被称为mock对象而已)
-------------现实的分隔线---------------
上面的说法只是对历史的一厢情愿的解读. 虽然根据Steve Freeman在 http://www.mockobjects.com/ 的描述, Mock的思想确实起源于开发者不想仅仅为了测试就为对象加上一堆getter而破坏面向对象, 从而开发出支持对交互进行测试的技术, 但后来随着对mock技术的深入理解和mock工具的日益强大, 出现了两种变化:
- Mock不再被定位为测试依赖隔离技术, 而是被用来支持系统中角色间的接口定义: "It turns out to be less interesting as a technique for isolating tests from third-party libraries than is widely thought. Mock Objects is misnamed. It is really a technique for identifying types in a system based on the roles that objects play" (http://static.mockobjects.com/files/mockrolesnotobjects.pdf ).
- Mock工具的日益强大被用来支持一种不同的测试世界观: "系统状态是一种不必要的依赖, 只要交互正确状态一定正确, 因此我希望所有测试都以直接断言SUT(System Under Test)正确的与外部依赖进行了交互的方式来写".
第一种变化并未普及, 因为它不是一种具体的几天可以学会的技术, 而是一种经验经历相关的认知. 经验少的人需要假以时日, 而经验多的人有都有各自的观点, 软件开发毕竟不够成熟.
第二种变化导致了mock的滥用. 是的, 强大的工具容易被滥用: 我能够断言交互顺序不意味着所有的测试都需要断言顺序, 我能够断言参数不意味着所有的测试我都去断言参数. 缺乏对应用场合的识别, 缺乏对系统的洞察, 导致大量脆弱的测试. 真正重要的是识别问题, 然后选择合适的工具. Mock工具也都支持Dummy, Stub, Fake等应用场景, 不要浪费了这些功能.
(之前对mock的理解, 请参阅"敏捷质疑: TDD"中"但是你们常用的 Mock 技术, 明显把单元测试推向白盒的境地"那一段)
分享到:
相关推荐
Python 提供了一个强大的库——`unittest.mock`,用于模拟(mock)对象、方法和类,以便在测试中隔离依赖关系,专注于测试目标代码的功能。本练习主要关注如何使用 `unittest.mock` 进行mock测试数据。 一、Mock...
在实际开发中,这个项目可以帮助我们理解如何在Vue.js和Iview的环境中实现拖拽排序功能,以及如何利用Mock.js来快速进行前端的单元测试和集成测试。通过研究这个测试DEMO,我们可以学习到以下关键知识点: 1. **Vue...
为什么要进行 Mock 测试? ------------------------- Mock 测试有很多优点,例如: * 帮助开发者更好地测试单元测试、集成测试和系统测试 * 解决不同单元之间的耦合问题 * 帮助开发者模拟一些难以构造或获取的...
描述中的链接指向了一篇关于Mock的博客文章,虽然具体内容未给出,但可以推测文章可能涉及了如何使用Mock进行测试、Mock工具的介绍以及Mock在实际项目中的应用案例。 在IT行业中,Mock工具有很多,比如Java中的...
MOCK挡板软件是一款专为测试人员设计的辅助工具,其主要目的是为了在软件测试阶段模拟实际环境或系统行为,以便于更有效地进行功能验证、性能测试、接口测试等多种测试任务。这款工具允许测试人员创建虚拟的服务或者...
在IT行业中,Mock技术是一种非常重要的测试方法,特别是在前端开发中。它允许开发者在不依赖实际后端服务的情况下,对应用程序进行单元测试和集成测试。`模拟mock.zip`这个压缩包文件显然与Mock技术相关,其中包含的...
Classes contained in spring-mock.jar: org.springframework.mock.jndi.ExpectedLookupTemplate.class org.springframework.mock.jndi.SimpleNamingContext.class org.springframework.mock.jndi....
Mock方法则是单元测试中的一个重要工具,用于模拟复杂系统中的依赖关系,以便孤立地测试目标代码。在本篇文章中,我们将深入探讨单元测试与Mock方法的相关知识点。 首先,让我们理解单元测试的基本概念。单元测试是...
性能测试mock,支持自定义mock文件和延时 java -jar perfmock-0.0.1-SNAPSHOT.jar --mockfile=xxx.json --latency=1000,2000 json文件样例,结构为json数组: [ { "description": "testpost", "request" : { "uri" :...
8. **Mock在TDD(Test-Driven Development)中的应用**:在TDD中,Mock对象帮助开发者编写最小化的、仅关注当前功能的测试,使得测试更加专注,反馈更加快速。 9. **集成测试中的Mock**:在集成测试中,Mock对象也...
Google C++测试框架,也被称为Google Test,是Google开发的一款强大的C++单元测试库,它为C++开发者提供了丰富的测试工具和功能。Google Mock(通常称为gmock)是Google Test框架的一部分,专门用于创建和使用模拟...
双重测试 为用户提供对支持! 请注意,testdouble-jest...当您调用testdouble-jest ,它会完成两件事:(1)添加对在Jest测试中使用td.replace()进行模块替换的支持,以及(2)添加一个新的顶级td.mock()函数,该函数
2. 获取Google Mock和Google Test的源代码,这里有一个名为"googletest-master.zip"的压缩包,解压后即为源代码目录。 3. 编译和安装Google Test和Google Mock。通常使用CMake构建系统,创建一个构建目录,运行`...
Google Mock 是一个强大的 C++ 单元测试框架,它允许开发者创建模拟对象(Mock Objects)以测试复杂的系统中各个组件的交互。Mock 对象能够模拟真实对象的行为,并且可以预设它们在特定调用下的响应,这对于隔离测试...
每种测试都有其特定目的,共同确保软件的质量。 总结来说,本文档提供的内容涵盖了单元测试的基本概念、Mock技术的运用、JUnit框架的详细讲解,以及Mockito、MockMVC和Mock.js等工具的使用。通过这些知识,开发者...
TOGAF certification mock test
- **作用**:确保每次测试都能在一个干净的环境中运行,避免资源泄露。 - **示例**:使用 `using` 语句管理数据库连接或临时文件。 4. **后门操作 (Back Door Manipulation)** - **定义**:通过非正常途径(如...
Spring针对J2EE的常用Web接口提供了Mock,这些组件被发布于spring-mock.jar,介绍如下: MockHttpServletRequest:HttpServletRequest接口的mock实现。 MockHttpServletResponse:HttpServletResponse接口的mock...
### 使用Mock对象在Java单元测试中的重要性及实践 #### 引言 在软件开发过程中,单元测试作为确保代码质量的重要环节,其有效性往往受到多种因素的影响,尤其是当待测方法依赖于外部资源如网络、数据库或其他复杂...