mock打桩之EasyMock

    TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只使用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。

    打桩(mock)是单元测试的重要内容。说难点,谈不上吧,能说出来想到的都不算是难点了。

    mock有两种。一种是静态打桩,一种是动态打桩。

    静态打桩就是在写测试代码之前根据需要打桩的类生成另外一个类,这个类就是mock object。

     动态打桩就是mock object是在测试代码运行的时候才生成的。比较常用的mock工具有EasyMock、Jmock、PowerMock、MockMvc。

    先说EasyMock,话说十年前,有天我同事跟我说他搜索easymock,发现百度排名第一的文章是我写的blog。好吧,侧面证明了当时关于这方面的资料是匮乏的。

easymock使用

    依赖

    代码中mock:

EasyMock设计

  • Mock对象能够模拟其他协同模块的行为,被测试模块通过与Mock对象协作,可以获得一个孤立的测试环境。
  • 使用Mock对象可以模拟在应用用不容易构造(如HttpServletRequest必须在Servlet容器中才能构造出来)和比较复杂的对象(如JDBC中的ResultSet对象),从而使测试顺利进行。
  • Mock对象可以根据享有的接口或类动态生成,不仅能避免额外的编码工作,同时也降低了引入错误的可能。
  • 简单即正义
  • 提供对接口的模拟,能够通过录制、回放、检查三步来完成大体的测试过程。

EasyMock源码解析

Mock对象的创建有两种方式:一种是通过EasyMock类提供的createMock方法创建,另一种是通过EasyMock类的createControl方法得到一个IMocksControl实例,再由这个IMocksControl实例创建Mock实例。

    而实际上这两种方法内部实现是一样的。

    MocksControl类中包含了两个重要的成员变量,分别是接口IMockBehavior和IMocksControlState的实例。

    IMocksBehavior的实现类MocksBehavior是EasyMock的核心类,它保存着一个ExpectedInvocationAndResult对象的一个列表,而ExpectedInvocationAndResult对象中包含着Mock对象方法调用和预期结果的映射。MocksBehavior类提供了addExpected和addActual方法用于添加预期行为和实际调用。

    MocksControl类中包含的另一个成员变量是IMocksControlState实例。IMocksControlState拥有两个不同的实现类:RecordState和ReplayState。顾名思义,RecordState是Mock对象在Record状态时的支持类,它提供了invoke方法在Record状态下的实现。他还提供了andReturn、andThrow、times等方法的实现。在ReplayState中,andReturn、andThrow、times等方法的实现都是抛出IllegalStateException,因为在Replay阶段,开发人员不应该再调用这些方法。

    当调用MocksControl的createMock方法时,该方法首选会生成一个JavaProxyFactory类的对象。JavaProxyFactory是接口IProxyFactory的实现类,它的主要功能就是通过java.lang.reflect.Proxy对指定的接口创建动态代理实例,也就是开发人员在外部看到的Mock对象。

    在创建动态代码的同时,应当提供InvocationHandler的实现类。MockInvocationHandler实现了这个接口,它的invoke方法主要的功能是根据Mock对象状态的不同而分别调用RecordState的invoke实现或是ReplayState的invoke实现。

    下面是备受吐槽的手绘时间:

简单再解释一下这张图:

    当EasyMock类的createMock方法被调用时,它首先创建一个MocksControl对象,并调用该对象的createMock方法创建一个JavaProxyFactory对象和一个MockInvocationHandler对象。JavaProxyFactory对象将MockInvocationHandler作为参数,通过java.lang.reflect.Proxy类的newProxyInstance静态方法创建一个动态代理。

    上面介绍的EasyMock创建的源码解析。可以参考上面的思路再看一下记录Mock对象预期行为的源码,在Replay状态下调用Mock对象的源码。

总结

    EasyMock是一个使用简单,源码也非常简单的工具。如果看spring系列源码有困难的同学可以看一下EasyMock的源码,思考一下EasyMock的设计理念和设计模式。

招贤纳士:

  • 新美大基础架构部招聘高级开发/专家。详细信息请点击公众号内“招贤纳士”菜单。
  • 爱奇艺招聘后台开发工程师,有意向请将简历发到BOSS邮箱:275824717@qq.com

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏智能大石头

XCode v9.6.2017.0830

新生命团队基础框架X组件,包括网络、数据库、安全、多线程、反射、序列化、模版引擎、服务代理、远程过程调用等模块,包括Mvc后台魔方、超级码神工具、消息队列等子系...

1370
来自专栏FreeBuf

注意了,使用Sqlmap的你可能踩中了“蜜罐”

* 本文原创作者:九如,本文属FreeBuf原创奖励计划,未经许可禁止转载 Par0:楔子 你站在桥上看风景,看风景的人在楼上看你, 明月装饰了你的窗子,你...

1816
来自专栏Gcaufy的专栏

async/await 带你逃离回调地狱

不曾见过天堂就不会畏惧地狱,async/await是目前尝试过的最好的异步回调解决方案,本文通过详细步骤给大家讲解。

4440
来自专栏IT技术精选文摘

Android性能优化来龙去脉总结

一款app除了要有令人惊叹的功能和令人发指交互之外,在性能上也应该追求丝滑的要求,这样才能更好地提高用户体验。

952
来自专栏恰同学骚年

.NET单元测试的艺术-3.测试代码

开篇:上一篇我们学习单元测试和核心技术:存根、模拟对象和隔离框架,它们是我们进行高质量单元测试的技术基础。本篇会集中在管理和组织单元测试的技术,以及如何确保在真...

663
来自专栏熊二哥

企业模式和设计模式快速入门

相信大家对GOF的23个设计模式和Martin Fowler的企业应用架构模式都有过了解,这部分的内容和知识非常驳杂,不过真正常用的模式并不多,比如单例模式、策...

1817
来自专栏Fundebug

Web应用架构入门之11个基本要素

译者: 读完这篇博客,你就可以回答一个经典的面试题:当你访问Google时,到底发生了什么?

983
来自专栏怀英的自我修炼

Java漫谈3

上次我们说道Java中的Hello World(以下简称HW)是什么样子的,还写了一段HW的输出程序。不知道你是否会有疑问,难道在Java的环境中只要输入这一句...

34111
来自专栏Timhbw博客

iOS面试中被面试官问到的问题答案(一)

2016-03-1016:30:14 发表评论 1,091℃热度 1.请你谈谈static和宏定义的区别。什么时候用static什么时候用宏定义。 让你声...

4518
来自专栏图像识别与深度学习

蓝牙项目开发流程

34110

扫码关注云+社区