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)部初始化了一個當前類的靜態(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注解即可。被其標注的方法會被編譯成普通的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
到此這篇關于Mockito mock Kotlin Object類方法報錯解決方法的文章就介紹到這了,更多相關Mockito mock Kotlin Object類方法報錯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot HandlerIntercepter攔截器修改request body數(shù)據(jù)的操作
這篇文章主要介紹了springboot HandlerIntercepter攔截器修改request body數(shù)據(jù)的操作,具有很好的參考價值,希望對大家有所幫助。2021-06-06
SpringBoot項目使用mybatis-plus代碼生成的實例詳解
mybatis-plus是mybatis的增強,不對mybatis做任何改變,涵蓋了代碼生成,自定義ID生成器,快速實現(xiàn)CRUD,自動分頁,邏輯刪除等功能。本文就來講講SpringBoot項目如何使用mybatis-plus實現(xiàn)代碼生成,需要的可以了解一下2022-10-10
java編程之基于SpringBoot框架實現(xiàn)掃碼登錄
本文將介紹基于SpringBoot + Vue + Android實現(xiàn)的掃碼登錄demo的總體思路,文中附含詳細示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-09-09

