比如我創建一個Kotlin
Object
類:ObjectMethod
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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
方法,會報錯。
1
2
3
4
5
6
7
8
9
10
11
|
@Test @DisplayName ( "mock普通的kotlin靜態方法" ) 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
里從形態跟使用上來看與靜態方法無二。但是編譯成java
代碼后,其本質其實是內部初始化了一個當前類的靜態常量實例INSTANCE
。這個INSTANCE
在kotlin
語法里被隱藏了,但在java里依然可以顯示訪問。ObjectMethod
編譯成java
后的代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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
本質上的原因是正常手段無法mock
靜態常量。如果想要使kotlin
的object
類中的方法能夠被mock
,只需在方法上加上@JvmStatic
注解即可。被其標注的方法會被編譯成普通的java
靜態方法。
上面說正常手段無法mock靜態常量,那么非正常手段呢?其實這個非正常手段就是通過反射將被mock
過的實例注入到ObjectMethod
中即可。
1
2
3
4
5
6
7
8
9
10
11
12
|
@Test @DisplayName ( "通過反射修改靜態常量來mock普通的kotlin靜態方法" ) 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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類方法報錯內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/scientificCommunity/article/details/120258224