Kotlin中Mockito3模拟get访问器失效并报空指针问题求助
这种问题我之前也碰到过,结合Mockito 3和mockito-inline的特性,咱们一步步来排查解决:
1. 先确认Mock对象是否真的被初始化了
你遇到的NullPointerException很大概率是因为mock对象本身是null,根本没被正确创建。
如果用了
@Mock注解:
别忘了在测试类上加上@ExtendWith(MockitoExtension::class)(Kotlin)或者@ExtendWith(MockitoExtension.class)(Java),或者在测试方法开头手动调用MockitoAnnotations.openMocks(this)来初始化所有@Mock标记的对象。没做这一步的话,mock就是null,调用mock.myVal自然会触发NPE。如果是手动创建mock:
必须用Mockito.mock(YourTargetClass::class.java)(Kotlin)或者Mockito.mock(YourTargetClass.class)(Java)来创建,别用new关键字实例化真实对象,不然那不是Mock。
2. 换用doReturn方式替代when(...).thenReturn
Mockito的when(mock.method()).thenReturn(...)是基于方法调用的语法,但对于final方法(比如Kotlin的val对应的getter默认是final的),有时候会因为字节码处理的顺序问题导致失效,甚至触发NPE。
换成doReturn的语法就更可靠,它是先指定返回值,再绑定到mock对象上,不会触发真实方法的调用:
Kotlin示例:
// 假设你的类是这样的 class MyService { val myVal: Boolean get() = true // 真实逻辑返回true } // 测试代码 @ExtendWith(MockitoExtension::class) class MyServiceTest { @Mock lateinit var mockService: MyService @Test fun testMockVal() { // 用doReturn避免触发真实getter doReturn(false).`when`(mockService).myVal assert(mockService.myVal == false) } }
Java示例:
public class MyService { private boolean myVal = true; public boolean isMyVal() { // 真实getter返回true return myVal; } } // 测试代码 @ExtendWith(MockitoExtension.class) public class MyServiceTest { @Mock private MyService mockService; @Test void testMockGetter() { doReturn(false).when(mockService).isMyVal(); assertEquals(false, mockService.isMyVal()); } }
3. 别直接访问字段,要通过getter方法
如果你直接写mock.myVal是在访问类的字段而不是调用getter方法,那Mockito根本拦截不到——Mock只能拦截方法调用,直接访问字段是绕过Mock的内存访问,自然会走真实的字段值(可能是null,导致NPE)。
不管是Java还是Kotlin,都要确保你Mock的是getter方法(Kotlin的val本质上是生成了getMyVal()方法,语法糖让你可以直接写myVal,Mockito还是能拦截到的,但前提是mock对象是有效的)。
4. 确认mockito-inline依赖配置正确
要确保你的构建工具里引入的是mockito-inline而不是普通的mockito-core,因为只有mockito-inline支持Mock final类、final方法和Kotlin的val属性:
Gradle配置(Kotlin DSL):
testImplementation("org.mockito:mockito-inline:3.12.4") // 版本和你的Mockito3匹配
Maven配置:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>3.12.4</version> <scope>test</scope> </dependency>
按这几步排查下来,基本就能解决Mock失效和NPE的问题了。
内容的提问来源于stack exchange,提问作者Haniyeh Ehsaninejad

