Error reporting solution of Mockito mock Kotlin Object method
- 2021-11-13 01:47:51
- OfStack
For example, if I create a
Kotlin
Object
Class:
ObjectMethod
package com.baichuan.example.unit_test
object ObjectMethod {
fun doSomething() {
println("this is ObjectMethod#doSomething")
}
@JvmStatic
fun doSomethingWithJvmStatic() {
println("this is ObjectMethod#doSomethingWithJvmStatic")
}
}
If I go straight to
mock
Of this class
doSomething
Method, will report an error.
@Test
@DisplayName("mock Ordinary kotlin Static method ")
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()
}
This is because
kotlin
In
object
Although the methods in the class are in the
kotlin
From the point of view of form and use, there is no static method 2. But compiled into
java
After the code, its essence is to initialize a static constant instance of the current class internally
INSTANCE
. This
INSTANCE
In
kotlin
It is hidden in syntax, but it can still display access in java.
ObjectMethod
Compile into
java
The code after this is as follows:
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);
}
}
So, you can't
mock
ObjectMethod#doSomething
The essential reason is that normal means can't
mock
Static constant. If you want to make
kotlin
Adj.
object
Methods in the class can be
mock
Simply add to the method
@JvmStatic
Annotations will do. The methods annotated by it will be compiled into ordinary
java
Static method.
It is said above that normal means cannot be mock static constant, so what about abnormal means? In fact, this abnormal means is that through reflection, it will be
mock
The passed instance is injected into the
ObjectMethod
Just medium.
@Test
@DisplayName(" Modify static constants by reflection to mock Ordinary kotlin Static method ")
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