比如我创建一个 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测试数据/scientificCommunity/blog-sample/tree/main/unit-test-sample
到此这篇关于Mockito mock Kotlin Object类方法报错解决方法的文章就介绍到这了,更多相关Mockito mock Kotlin Object类方法报错内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
原文链接:https://blog.csdn.net/scientificCommunity/article/details/120258224
查看更多关于Mockito mock Kotlin Object类方法报错解决方法的详细内容...