為什么需要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),我們將立即處理