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-02
SpringBoot部署到Linux讀取resources下的文件及遇到的坑
本文主要給大家介紹SpringBoot部署到Linux讀取resources下的文件,在平時業(yè)務(wù)開發(fā)過程中,很多朋友在獲取到文件內(nèi)容亂碼或者文件讀取不到的問題,今天給大家分享小編遇到的坑及處理方案,感興趣的朋友跟隨小編一起看看吧2021-06-06
Mybatis中如何設(shè)置sqlSession自動提交
在MyBatis中,默認(rèn)情況下,獲取的SqlSession對象不會自動提交事務(wù),這意味著在進(jìn)行更新、刪除或插入等操作后,需要顯式調(diào)用commit方法來提交事務(wù),但是,可以在獲取SqlSession時通過將openSession方法的參數(shù)設(shè)置為true2024-09-09
Java 實現(xiàn)完整功能的學(xué)生管理系統(tǒng)實例
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java實現(xiàn)一個完整版學(xué)生管理系統(tǒng),大家可以在過程中查缺補漏,提升水平2021-11-11

