Mockito mock Kotlin Object類方法報(bào)錯(cuò)解決方法
比如我創(chuàng)建一個(gè)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方法,會(huì)報(bào)錯(cuò)。
@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()
}
這是因?yàn)?code>kotlin里的object類里的方法雖然在kotlin里從形態(tài)跟使用上來(lái)看與靜態(tài)方法無(wú)二。但是編譯成java代碼后,其本質(zhì)其實(shí)是內(nèi)部初始化了一個(gè)當(dāng)前類的靜態(tài)常量實(shí)例INSTANCE。這個(gè)INSTANCE在kotlin語(yǔ)法里被隱藏了,但在java里依然可以顯示訪問(wèn)。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ì)上的原因是正常手段無(wú)法mock靜態(tài)常量。如果想要使kotlin的object類中的方法能夠被mock,只需在方法上加上@JvmStatic注解即可。被其標(biāo)注的方法會(huì)被編譯成普通的java靜態(tài)方法。
上面說(shuō)正常手段無(wú)法mock靜態(tài)常量,那么非正常手段呢?其實(shí)這個(gè)非正常手段就是通過(guò)反射將被mock過(guò)的實(shí)例注入到ObjectMethod中即可。
@Test
@DisplayName("通過(guò)反射修改靜態(tài)常量來(lá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類方法報(bào)錯(cuò)解決方法的文章就介紹到這了,更多相關(guān)Mockito mock Kotlin Object類方法報(bào)錯(cuò)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于springboot 長(zhǎng)輪詢的實(shí)現(xiàn)操作
這篇文章主要介紹了基于springboot 長(zhǎng)輪詢的實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
Java適配器模式之如何靈活應(yīng)對(duì)不匹配的接口
本文介紹了Java中的適配器模式,包括對(duì)象適配器模式和接口適配器模式,適配器模式通過(guò)將一個(gè)類的接口轉(zhuǎn)換成客戶期望的另一個(gè)接口,解決了不同接口之間的不兼容問(wèn)題,它提高了系統(tǒng)的靈活性、復(fù)用性和解耦性,需要的朋友可以參考下2024-10-10
Java 中責(zé)任鏈模式實(shí)現(xiàn)的三種方式
本文重點(diǎn)給大家介紹java中如何編寫責(zé)任鏈模式。主要從下面3個(gè)框架中的代碼中介紹。非常不錯(cuò),需要的朋友參考下吧2017-09-09
springboot HandlerIntercepter攔截器修改request body數(shù)據(jù)的操作
這篇文章主要介紹了springboot HandlerIntercepter攔截器修改request body數(shù)據(jù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2021-06-06
SpringBoot項(xiàng)目使用mybatis-plus代碼生成的實(shí)例詳解
mybatis-plus是mybatis的增強(qiáng),不對(duì)mybatis做任何改變,涵蓋了代碼生成,自定義ID生成器,快速實(shí)現(xiàn)CRUD,自動(dòng)分頁(yè),邏輯刪除等功能。本文就來(lái)講講SpringBoot項(xiàng)目如何使用mybatis-plus實(shí)現(xiàn)代碼生成,需要的可以了解一下2022-10-10
java編程之基于SpringBoot框架實(shí)現(xiàn)掃碼登錄
本文將介紹基于SpringBoot + Vue + Android實(shí)現(xiàn)的掃碼登錄demo的總體思路,文中附含詳細(xì)示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-09-09
詳解java實(shí)現(xiàn)HTTP請(qǐng)求的三種方式
這篇文章主要介紹了java實(shí)現(xiàn)HTTP請(qǐng)求的三種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04

