测试emitChatMessage函数时any(JSONObject::class.java)空指针问题求助
解决socketDataSource.emit测试中的空指针异常
问题场景
我正在测试emitChatMessage函数,实现代码如下:
fun emitChatMessage(chatId: String, sender: String, content: String, messageType: String) { val message = JSONObject().apply { put("chatId", chatId) put("sender", sender) put("content", content) put("messageType", messageType) } socketDataSource.emit(CommonFunctionAndVariables.CHAT_KEYS.NEW_MESSAGE, message) }
编写的JUnit测试用例尝试捕获socketDataSource.emit传入的JSONObject进行验证:
@Test fun `test Emit Chat Message`() { val chatId = "64393f76ca21bdf658d19bd2" val sender = "John" val content = "Hello" val messageType = "text" val capturedMessage = mutableListOf<JSONObject>() `when`(socketDataSource.emit(anyString(), any(JSONObject::class.java))).thenAnswer { val message = it.arguments[1] as JSONObject capturedMessage.add(message) } repository.emitChatMessage(chatId, sender, content, messageType) }
运行测试时触发空指针异常:
any(JSONObject::class.java) must not be null java.lang.NullPointerException: any(JSONObject::class.java) must not be null at cc.mekanism.chatconcept.feature_send_message.domain.repository.SocketRepositoryTest.test Emit Chat Message(SocketRepositoryTest.kt:37) ...(省略后续栈跟踪)
SocketDataSource接口定义:
package cc.mekanism.chatconcept.feature_send_message.data.remote import org.json.JSONObject interface SocketDataSource { fun connect(userId: String, authToken: String) fun emit(event: String, data: JSONObject) fun on(event: String, listener: (data: JSONObject) -> Unit) fun disconnect() }
错误原因
问题出在Mockito的参数匹配器any(JSONObject::class.java)上:
- Kotlin中
SocketDataSource.emit的data参数是非空类型JSONObject,但any(Class::class.java)会返回null - 当Mockito尝试用
null匹配非空参数时,触发Kotlin的非空检查,抛出空指针异常
解决方案
推荐使用ArgumentCaptor来捕获参数,这种方式更简洁规范,也能避免匹配器的空指针问题:
步骤1:定义ArgumentCaptor
在测试类中或测试方法内定义JSONObject类型的参数捕获器:
private val messageCaptor = ArgumentCaptor.forClass(JSONObject::class.java)
步骤2:捕获并验证参数
修改测试逻辑,用verify配合捕获器来获取emit方法传入的JSONObject:
@Test fun `test Emit Chat Message`() { val chatId = "64393f76ca21bdf658d19bd2" val sender = "John" val content = "Hello" val messageType = "text" // 执行目标方法 repository.emitChatMessage(chatId, sender, content, messageType) // 验证emit方法被调用,并捕获传入的JSONObject参数 verify(socketDataSource).emit(eq(CommonFunctionAndVariables.CHAT_KEYS.NEW_MESSAGE), messageCaptor.capture()) // 获取捕获的参数并验证字段值 val capturedMessage = messageCaptor.value assertEquals(chatId, capturedMessage.getString("chatId")) assertEquals(sender, capturedMessage.getString("sender")) assertEquals(content, capturedMessage.getString("content")) assertEquals(messageType, capturedMessage.getString("messageType")) }
替代方案:使用Mockito-Kotlin的匹配器
如果项目中引入了mockito-kotlin依赖,可以直接用泛型版any<JSONObject>()来替代any(JSONObject::class.java),它会正确处理Kotlin的非空类型:
`when`(socketDataSource.emit(anyString(), any<JSONObject>())).thenAnswer { val message = it.arguments[1] as JSONObject // 后续逻辑 }
注意:使用此方案需要确保依赖中包含mockito-kotlin,比如Gradle依赖:
testImplementation "org.mockito.kotlin:mockito-kotlin:4.1.0"
内容的提问来源于stack exchange,提问作者Jay Patel
相关产品推荐
相关产品推荐

