Mockito mock Kotlin Object類方法報錯解決方法
比如我創(chuàng)建一個Kotlin
Object
類:ObjectMethod
package com.baichuan.example.unit_test object ObjectMethod { fun doSomething() { println("this is ObjectMethod#doSomething") } @JvmStatic fun doSomethingWithJvmStatic() { println("this is ObjectMethod#doSomethingWithJvmStatic") } }
如果我直接去mock
該類的doSomething
方法,會報錯。
@Test @DisplayName("mock普通的kotlin靜態(tài)方法") fun testMockKotlinObject() { Assertions.assertThrows(MissingMethodInvocationException::class.java) { Mockito.mockStatic(ObjectMethod::class.java).`when`<Unit>( ObjectMethod::doSomething ).thenAnswer { println("this is mocked Object#doSomething") } } ObjectMethod.doSomething() }
這是因為kotlin
里的object
類里的方法雖然在kotlin
里從形態(tài)跟使用上來看與靜態(tài)方法無二。但是編譯成java
代碼后,其本質(zhì)其實是內(nèi)部初始化了一個當(dāng)前類的靜態(tài)常量實例INSTANCE
。這個INSTANCE
在kotlin
語法里被隱藏了,但在java里依然可以顯示訪問。ObjectMethod
編譯成java
后的代碼如下:
public final class ObjectMethod { @NotNull public static final ObjectMethod INSTANCE = new ObjectMethod(); private ObjectMethod() { } public final void doSomething() { String var1 = "this is ObjectMethod#doSomething"; boolean var2 = false; System.out.println(var1); } @JvmStatic public static final void doSomethingWithJvmStatic() { String var0 = "this is ObjectMethod#doSomethingWithJvmStatic"; boolean var1 = false; System.out.println(var0); } }
所以,不能mock
ObjectMethod#doSomething
本質(zhì)上的原因是正常手段無法mock
靜態(tài)常量。如果想要使kotlin
的object
類中的方法能夠被mock
,只需在方法上加上@JvmStatic
注解即可。被其標(biāo)注的方法會被編譯成普通的java
靜態(tài)方法。
上面說正常手段無法mock靜態(tài)常量,那么非正常手段呢?其實這個非正常手段就是通過反射將被mock
過的實例注入到ObjectMethod
中即可。
@Test @DisplayName("通過反射修改靜態(tài)常量來mock普通的kotlin靜態(tài)方法") fun testMockKotlinObjectMethodByReflection() { val mock = Mockito.mock(ObjectMethod::class.java) Mockito.`when`(mock.doSomething()).then { print("this is mocked ObjectMethod by reflection") } val declaredMethod = ObjectMethod::class.java.getDeclaredField("INSTANCE") ReflectionUtils.setFinalStatic(declaredMethod, mock) ObjectMethod.doSomething() }
ReflectionUtils
package com.baichuan.example.unit_test import java.lang.reflect.Field import java.lang.reflect.Modifier object ReflectionUtils { @Throws(Exception::class) fun setFinalStatic(field: Field, newValue: Any) { field.isAccessible = true val modifiersField: Field = Field::class.java.getDeclaredField("modifiers") modifiersField.isAccessible = true modifiersField.setInt(field, field.modifiers and Modifier.FINAL.inv()) field.set(null, newValue) } }
github
https://github.com/scientificCommunity/blog-sample/tree/main/unit-test-sample
到此這篇關(guān)于Mockito mock Kotlin Object類方法報錯解決方法的文章就介紹到這了,更多相關(guān)Mockito mock Kotlin Object類方法報錯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java語言Consistent Hash算法學(xué)習(xí)筆記(代碼示例)
這篇文章主要介紹了Java語言Consistent Hash算法學(xué)習(xí)筆記(代碼示例),分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-02-02SpringBoot部署到Linux讀取resources下的文件及遇到的坑
本文主要給大家介紹SpringBoot部署到Linux讀取resources下的文件,在平時業(yè)務(wù)開發(fā)過程中,很多朋友在獲取到文件內(nèi)容亂碼或者文件讀取不到的問題,今天給大家分享小編遇到的坑及處理方案,感興趣的朋友跟隨小編一起看看吧2021-06-06Mybatis中如何設(shè)置sqlSession自動提交
在MyBatis中,默認(rèn)情況下,獲取的SqlSession對象不會自動提交事務(wù),這意味著在進(jìn)行更新、刪除或插入等操作后,需要顯式調(diào)用commit方法來提交事務(wù),但是,可以在獲取SqlSession時通過將openSession方法的參數(shù)設(shè)置為true2024-09-09Java 實現(xiàn)完整功能的學(xué)生管理系統(tǒng)實例
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java實現(xiàn)一個完整版學(xué)生管理系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2021-11-11SpringBoot2.3新特性優(yōu)雅停機(jī)詳解
這篇文章主要介紹了SpringBoot2.3新特性優(yōu)雅停機(jī)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05