为什么需要MockK
在MockK之前,已经有一大批测试库可以用于Mocking,其中有名的也有很多,比如Mockito, PowerMock,Jmockit等等,但是他们都有各自的缺陷,这些缺陷也和Kotlin的特性有关。
关键字
在 Kotlin 裡面 when是关键字,Mockito 的when ,必须加上反引号才能使用:
`when`(xxxx).thenReturn(xxx) |
如果看起来不舒服,也可以舍弃 Mockito 改用 mockito-kotlin。
在 mockito-kotlin中使用了whenever代替when,也有更简洁的写法,但是归根到底还是在使用Mockito的Api,所以功能上依然有局限性。
Mock Kotlin的类时报错
org.mockito.exceptions.base.MockitoException: Cannot mock/spy class com.joetsai.kotlinunittest.token.TokenRepository Mockito cannot mock/spy because : — final class |
这是因为Kotlin中类都是默认final类型,如果需要mock,则需要显示的加上open标识符,如果有100个类,则需要加100次,这也太麻烦了…
静态方法如何Mock
众所周知,Mockito是不支持静态方法的,如果想使用就需要使用PowerMock,但是PowerMock也有缺点。
使用流程也比较繁琐
Mockito与PowerMock是不同团队开发的,更新速度慢而且有兼容性问题。
Jmockit
完全与kotlin不兼容…
MockK使用示例
普通使用
fun test() { val mother = mockk<Mother>() every { mother.giveMoney() } returns 30 // when().thenReturn() in Mockito assertEquals(30, mother.giveMoney()) } |
mockkObject
object Son { fun test5(): Int { return 5 } } mockkObject(Son) every { Son.test5() } returns 10 assertEquals(10, Son.test5()) |
mockkStatic
class Son { Static int test5() { return 5 } } |
@test fun test() { mockkStatic(Son::class) every { Son.test5() } returns 10 assertEquals(10, Son.test5()) } |
mock private method
class Son { public int publicResult() { return privateResult() } private int privateReuslt() { return 5 } } |
@test fun test() { val son = mockk<Son>() every { son["privateResult"]() } returns 10 assertEquals(10, son.publicResult()) } |
Context Mock
在某些Android某些用户自定义的类中,需要Context才能初始化。
class Utils { public static void initialize(Context context) { instance = builder.build(context); } public static synchronized Utils getInstance() { if (instance == null) { throw new IllegalStateException("you must call initialize first"); } return instance; } } |
有两种初始化方式:
直接mock context
val context = mockk<Context>() Utils.init(context) Utils.getInstance().xxxx() |
直接mock Util
val mockApplicationContext = mockk<Context>() val utils = mockk<Utils.init>() mockkStatic(Utils.init::class) every { Utils.getInstance() } returns utils every { utils.test() } returns null ...... |
遇到的一些小坑
从介绍来看,在mockStatic时只能mock非final类,所以如果mock系统自带的System类会直接报错。
在Android instrument test时,需要设备Android版本>=9。
在最新版(1.10.2)的MockK中,需要kotlin版本>=1.3.61
最后
因为当前项目是java和kotlin混编的,所以举得例子中也有不少java的demo。
如果大家还有其他遇到的问题或者坑,欢迎留言。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理