Mockito|Mockito mock Kotlin Object类方法报错解决方法
比如我创建一个Kotlin
Object
类:ObjectMethod
package com.baichuan.example.unit_testobject ObjectMethod {fun doSomething() {println("this is ObjectMethod#doSomething")}@JvmStaticfun doSomethingWithJvmStatic() {println("this is ObjectMethod#doSomethingWithJvmStatic")}}
如果我直接去
mock
该类的doSomething
方法,会报错。@Test@DisplayName("mock普通的kotlin静态方法")fun testMockKotlinObject() {Assertions.assertThrows(MissingMethodInvocationException::class.java) {Mockito.mockStatic(ObjectMethod::class.java).`when`(ObjectMethod::doSomething).thenAnswer { println("this is mocked Object#doSomething") }}ObjectMethod.doSomething()}
这是因为
kotlin
里的object
类里的方法虽然在kotlin
里从形态跟使用上来看与静态方法无二。但是编译成java
代码后,其本质其实是内部初始化了一个当前类的静态常量实例INSTANCE
。这个INSTANCE
在kotlin
语法里被隐藏了,但在java里依然可以显示访问。ObjectMethod
编译成java
后的代码如下:public final class ObjectMethod {@NotNullpublic 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); }@JvmStaticpublic 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
中即可。@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
package com.baichuan.example.unit_testimport java.lang.reflect.Fieldimport java.lang.reflect.Modifierobject ReflectionUtils {@Throws(Exception::class)fun setFinalStatic(field: Field, newValue: Any) {field.isAccessible = trueval modifiersField: Field = Field::class.java.getDeclaredField("modifiers")modifiersField.isAccessible = truemodifiersField.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|Mockito mock Kotlin Object类方法报错解决方法】到此这篇关于Mockito mock Kotlin Object类方法报错解决方法的文章就介绍到这了,更多相关Mockito mock Kotlin Object类方法报错内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- android防止连续点击的简单实现(kotlin)
- retrofit2-kotlin-coroutines-adapter|retrofit2-kotlin-coroutines-adapter 超时引起的崩溃
- Kotlin泛型的高级特性(六)
- Kotlin基础(10)-代理模式在kotlin中的使用
- Android|Android Kotlin实现AIDL跨进程通信
- Mockito|Mockito mock void methods Example
- 更完整的单例模式(java|更完整的单例模式(java, kotlin)
- Kotlin学习笔记——BroadCast
- kotlin|kotlin example
- Kotlin协程