WHAT--定义
Mock测试就是在测试过程当中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来建立以便测试的测试方法(来自百度百科)。通俗点讲,就是:作个假对象、响应来实现某种特定场景的测试。java
WHY--使用缘由
(1)底层数据复杂,依赖严重等状况,按照真实的场景去使用,耗时、成本较大等;
(2)依赖的底层单元还没有开发完成,或现有资源难以知足当前模块的测试需求;
(3)一些特定的异常场景,较难复现等;mysql
WHEN & WHERE--使用场景
--其实WHY里面,已经回答了这个问题。如下两条也是使用原则,没必要每一个单元测试都使用Mock。
(1)单元测试/接口测试中测试对象依赖其余对象,这些对象的构造复杂、耗时或者根本没法构
造(未交付);
----简单的场景,不必使用,可能会耗时更多。异常场景、复杂场景、影响工做效率场景等建议使用。
(2)咱们只测试对象内部逻辑的质量,不关心依赖对象的逻辑正确性和稳定性;
----即:底层的代码已确保由底层保障,不须要调用方关心。sql
Dummy Object,测试代码须要Dummy Object是由于有了它才能经过编译,测试才能跑起来,但其实测试中可能根本就用不到它。数据库
eg1:函数
例如,建立BlogService 须要 BlogDao,但你可能测试BlogService 的一个方法,它根本就没用到BlogDao。此时,你能够用 new BlogService(new NullBlogDao()), NullBlogDao 就是Dummy Object,由于它的存在只是为了经过编译,它根本就不参与测试。单元测试
eg2:测试
图中main函数,须要统计对象个数。须要实例PersonImpl的对象,然而PersonImpl是Person接口的实现类,因此必须实现Person接口的抽象方法study(),因此此时PersonImpl类中的实现方法在main函数中并无起到任何做用,可是必须写上,确保程序不报错,这时候study()就能够理解为一个Dummy。spa
Stub 参与测试, 但你不在意它是什么时候何地以何种方式参与测试的,它的存在是为了让测试跑起来,在测试过程当中产生的调用提供预备好的应答,一般不该答计划以外的任何事,很是常见的状况是你须要它提供一些返回值。例如,你能够用HttpContextStub 来代替真正的HttpContext, 用它提供例如SessionId, ResquestParameter 之类的值。你的测试可能会用到这些值,但你不会去验证是否是getSessionId() 被调用了,更不会去验证它是什么时候何地以何种方式被调用的。code
如图中,跳过查mysql的数据操做,模拟测试桩来代替查数据库的步骤,不须要关心查mysql的操做,只关注数据按照这个格式返回。对象
spy 能够理解为侦查,它负责汇报状况,持续追踪什么方法被调用了,以及调用过程当中传递了哪些参数。你能用它来实现测试断言,好比一个特定的方法是否被调用或者是否使用正确的参数调用。当你须要测试两个对象间的某些协议或者关系时会很是有用。
public void testRemoveFlightLogging_recordingTestStub() throws Exception { // Fixture setup FlightDto expectedFlightDto = createAnUnregFlight(); FlightManagementFacade facade = new FlightManagementFacadeImpl(); // Test Double setup AuditLogSpy logSpy = new AuditLogSpy(); facade.setAuditLog(logSpy); // Exercise facade.removeFlight(expectedFlightDto.getFlightNumber()); // Verify state assertFalse("flight still exists after being removed", facade.flightExists( expectedFlightDto. getFlightNumber())); // Verify indirect outputs using retrieval interface of spy assertEquals("number of calls", 1, logSpy.getNumberOfCalls()); assertEquals("action code", Helper.REMOVE_FLIGHT_ACTION_CODE, logSpy.getActionCode()); assertEquals("date", helper.getTodaysDateWithoutTime(), logSpy.getDate()); assertEquals("user", Helper.TEST_USER_NAME, logSpy.getUser()); assertEquals("detail", expectedFlightDto.getFlightNumber(), logSpy.getDetail()); }
fake 是一个具有完整功能实现和行为的对象,行为上来讲它和这个类型的真实对象上同样,但不一样于它所模拟的类,它使测试变得更加容易。一个典型的例子是使用内存中的数据库来生成一个数据持久化对象,而不是去访问一个真正的生产环境的数据库。
常常,咱们会把Fake Object和Test Stub搞混,由于它们都和外部没有交互,对内部的输入输出也不进行验证。不一样的是,Fake Object并不关注SUT内部的间接输入(indirect inputs)或间接输出(indirect outputs),它仅仅是用来替代一个实际的对象,而且拥有几乎和实际对象同样的功能,保证SUT可以正常工做。实际对象过度依赖外部环境,Fake Object能够减小这样的依赖。
mock 与 spy 相似,但在使用上有些许不一样。spy 追踪全部的方法调用,并在过后让你写断言,而 mock 一般须要你事先设按期望。你告诉它你指望发生什么,而后执行测试代码并验证最后的结果与事先定义的指望是否一致。