测试与Mock

本文介绍Mock技术在单元测试中的应用,通过示例展示如何使用Mockito框架模拟接口,实现解耦测试,提高开发效率。

本次 more time 为大家带来 Mock 技术。Mock技术可以让你专注自己的逻辑,和同事用接口交流,从而自由飞翔,按时下班。

Mock就是模拟的意思。模拟一个类,而不用真实的类。这在单元测试里面的好处是解耦。即我只对这一个类的功能进行验证,和这个类相关的其他类,都被我Mock,他们的表现是由我决定的。

最简单的 Mock手段,是写一个类去继承真实的类,这固然可以,代码量不大并且易读。但是如果要 Mock的是一个复杂的接口,有一堆方法需要去实现,并且这个接口没有默认实现。那么就不能这样了。这时就需要 Mock 框架。

Spring Boot Test[1] 推荐 Java 用 Mock框架是 Mockito[2], Kotlin 用 MockK[3],但 Mockito 也是兼容 Kotlin的,只是 Mockk 提供了 Kotlin DSL 的语法更加优雅。接下来的一个小场景里我会使用 Kotlin + Mocktion + JUnit4。

Mockito 提供了 2种语法,一种是when…then…verify 的,一种是行为驱动开发BDD[4]的语法。given…will…then。老的语法和BDD语法并没有多大的不同,为了节能起见,只讲BDD的语法。

下面给一个场景,来讲述 Mock 技术。小王有个任务,写一个类,叫Y运算器。Y运算器的核心是y函数。y(a,b,c) = a + b * c。
但小王不会写乘法,因此小亦说我帮你写一个,你先等着吧。
小王是 moretime 的忠实读者,觉得被小亦 block 自己,这种事情不能忍,于是求小亦先写一个接口。
小亦便老老实实写了个接口。

interface Multiplier {
    fun mul(a: Double, b: Double): Double
}

小王很开心,于是开始写自己代码。
小王先写个类的雏形。

class Y {
    fun y(a: Double, b: Double, c: Double) = 0.0
}

小王是一个TDD爱好者,于是他开始写测试代码。
当然,严格的TDD是先写测试代码,然后测试失败,不能编译也算测试失败,然后再来修复。我觉得TDD刚提出来的时候肯定没什么好的IDE,不然直接下测试红一片谁能忍?所以先写个基本的模板,再写测试时可以的。

	@Test
	fun shouldReturn7whenCalcY123() {
        val y = Y()
		val ans = y.y(1.0, 2.0, 3.0)
		assertEquals(7.0, ans)
	}

显然不过
报了个错

junit.framework.AssertionFailedError: 
Expected :7.0
Actual   :0.0

OK,开始进入TDD的红绿循环了。
小王修改自己的代码,用上了小亦的接口 Multiplier

class Y(private val multiplier: Multiplier) {
    fun y(a: Double, b: Double, c: Double) = a + multiplier.mul(b, c)
}

OK,写好了。肯定是对的。不过很尴尬,需要修改测试。这实际上也不是严格的TDD,不过无所谓了
但问题来了,小王这里目前并没有 Multiplier 的实现类,这也就意味着它没办法实例化一个Y。那就没办法测试了
好在小王是一个TDD爱好者,他使用的Mockito
Spring 里用 Mockito 直接 @Mock 注解来一波就好了
于是测试类改成这样

	@Mock
	lateinit var mockMultiplier: Multiplier

	@Test
	fun shouldReturn7whenCalcY123() {
        val y = Y(mockMultiplier)
		val ans = y.y(1.0, 2.0, 3.0)
		assertEquals(7.0, ans)
	}

这样Y就能实例化了,再次运行测试

Expected :7.0
Actual   :1.0

结果是 1.0,说明这个 mockMultiplier.mul() 方法返回的是 0
这里便有1个知识点
Mock 对象的函数结果都是默认值
基本类型是0,对象就是 null
之后加一行
变成

	@Test
	fun shouldReturn7whenCalcY123() {
		given(mockMultiplier.mul(2.0, 3.0)).willReturn(6.0)
        val y = Y(mockMultiplier)
		val ans = y.y(1.0, 2.0, 3.0)
		assertEquals(7.0, ans)
	}

再次运行便通过了测试
这就是 given.willReturn的BDD写法
小王通过了测试,便收工回家。小亦一个人加班写好了乘法器。第二天给了小王

class MultiplierImpl: Multiplier {
    override fun mul(a: Double, b: Double) = a * b
} 

小王心想小亦这不靠谱的以后万一把这个类给改错了,不行,我要加一个新的测试
于是写了个集成测试

	@Test
	fun shouldReturn7whenCalcY123UsingMultiplierImpl() {
		val y = Y(MultiplierImpl())
		val ans = y.y(1.0, 2.0, 3.0)
		assertEquals(7.0, ans)
	}

也通过了测试,说明没问题,可以开始下一个任务了

总结

  1. @Mock 可以Mock 出一个对象,类型是类或是接口都行
  2. given().willReturn() 的定义Mock对象的行为

延伸阅读

  1. 关于单测函数名的规范,可以看《码出高效:Java开发手册》[5] 的第8章单元测试
  2. 关于 BDD,可以研究研究 cucumber [6],我有空也看看
  3. mockito 除了上文的 Mock 之外,还有 then , spy 这两个函数 。 then 可以验证一个方法是否被调用,因为可能被间接调用; spy 可以完全继承一个类,并重写新的方法
  4. Java测试驱动开发》[7] 也可以看看,这个有电子版

参考
[1] https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-testing
[2] https://site.mockito.org/
[3] https://mockk.io/
[4] https://en.wikipedia.org/wiki/Behavior-driven_development
[6] https://book.douban.com/subject/30333948/
[7] https://cucumber.io/
[8] https://book.douban.com/subject/27116715/

欢迎关注
在这里插入图片描述

【四轴飞行器】非线性三自由度四轴飞行器模拟器研究(Matlab代码实现)内容概要:本文围绕非线性三自由度四轴飞行器模拟器的研究展开,重点介绍基于Matlab代码实现的四轴飞行器动力学建模仿真方法。研究构建了考虑非线性特性的飞行器数学模型,涵盖姿态动力学运动学方程,实现了三自由度(滚转、俯仰、偏航)的精确模拟。文中详细阐述了系统建模过程、控制算法设计思路及仿真结果分析,帮助读者深入理解四轴飞行器的飞行动力学特性控制机制;同时,该模拟器可用于算法验证、控制器设计教学实验。; 适合人群:具备一定自动控制理论基础Matlab编程能力的高校学生、科研人员及无人机相关领域的工程技术人员,尤其适合从事飞行器建模、控制算法开发的研究生初级研究人员。; 使用场景及目标:①用于四轴飞行器非线性动力学特性的学习仿真验证;②作为控制器(如PID、LQR、MPC等)设计测试的仿真平台;③支持无人机控制系统教学科研项目开发,提升对姿态控制系统仿真的理解。; 阅读建议:建议读者结合Matlab代码逐模块分析,重点关注动力学方程的推导实现方式,动手运行并调试仿真程序,以加深对飞行器姿态控制过程的理解。同时可扩展为六自由度模型或加入外部干扰以增强仿真真实性。
基于分布式模型预测控制DMPC的多智能体点对点过渡轨迹生成研究(Matlab代码实现)内容概要:本文围绕“基于分布式模型预测控制(DMPC)的多智能体点对点过渡轨迹生成研究”展开,重点介绍如何利用DMPC方法实现多智能体系统在复杂环境下的协同轨迹规划控制。文中结合Matlab代码实现,详细阐述了DMPC的基本原理、数学建模过程以及在多智能体系统中的具体应用,涵盖点对点转移、避障处理、状态约束通信拓扑等关键技术环节。研究强调算法的分布式特性,提升系统的可扩展性鲁棒性,适用于多无人机、无人车编队等场景。同时,文档列举了大量相关科研方向代码资源,展示了DMPC在路径规划、协同控制、电力系统、信号处理等多领域的广泛应用。; 适合人群:具备一定自动化、控制理论或机器人学基础的研究生、科研人员及从事智能系统开发的工程技术人员;熟悉Matlab/Simulink仿真环境,对多智能体协同控制、优化算法有一定兴趣或研究需求的人员。; 使用场景及目标:①用于多智能体系统的轨迹生成协同控制研究,如无人机集群、无人驾驶车队等;②作为DMPC算法学习仿真实践的参考资料,帮助理解分布式优化模型预测控制的结合机制;③支撑科研论文复现、毕业设计或项目开发中的算法验证性能对比。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注DMPC的优化建模、约束处理信息交互机制;按文档结构逐步学习,同时参考文中提及的路径规划、协同控制等相关案例,加深对分布式控制系统的整体理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值