You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:47:53