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

Android Intent扩展putData测试:extras为空的原因与解决

Android Intent扩展函数单元测试失败:extras为null的原因及解决方法

问题描述

编写了以下Android Intent的Kotlin扩展函数:

import android.content.Intent
import android.os.Parcelable
import java.io.Serializable

fun Intent.addNewTaskFlags(): Intent = apply {
    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_ANIMATION)
}

fun Intent.putData(dataMap: Map<String, Any?>): Intent = apply {
    dataMap.forEach { (key, data) -
        data?.let {
            put(key, it)
        }
    }
}

private fun Intent.put(key: String, value: Any) {
    when (value) {
        is String -
            putExtra(key, value)
        is Int -
            putExtra(key, value)
        is Boolean -
            putExtra(key, value)
        is Long -
            putExtra(key, value)
        is Double -
            putExtra(key, value)
        is Parcelable -
            putExtra(key, value)
        is Serializable -
            putExtra(key, value)
        else -
            throw IllegalArgumentException("Incompatible data type: ${value.javaClass}")
    }
}

对应的单元测试代码:

class IntentExtensionTest {

    @Test
    fun testAddNewTaskFlags() {
        // When
        val mockIntent = spyk(Intent())
        mockIntent.addNewTaskFlags()

        // Then
        verify {
            mockIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_ANIMATION)
        }
    }

    @Test
    fun testPutData() {
        // Given
        val parcelableValue = mockk<Parcelable>()
        val serializableValue = mockk<Serializable>()

        // When
        val intent = Intent().putData(
            mapOf(
                STRING_KEY to STRING_VALUE,
                INT_KEY to INT_VALUE,
                BOOLEAN_KEY to BOOLEAN_VALUE,
                LONG_KEY to LONG_VALUE,
                DOUBLE_KEY to DOUBLE_VALUE,
                PARCELABLE_KEY to parcelableValue,
                SERIALIZABLE_KEY to serializableValue
            )
        )

        // Then
        intent.run {
            val extras = extras ?: throw AssertionError("Intent extras are null")

            assertEquals(STRING_VALUE, extras.getString(STRING_KEY))
            assertEquals(INT_VALUE, extras.getInt(INT_KEY, -1))
            assertEquals(BOOLEAN_VALUE, extras.getBoolean(BOOLEAN_KEY, false))
            assertEquals(LONG_VALUE, extras.getLong(LONG_KEY, -1L))
            assertEquals(DOUBLE_VALUE, extras.getDouble(DOUBLE_KEY, -1.0))
            assertEquals(parcelableValue, extras.getParcelable(PARCELABLE_KEY))
            assertEquals(serializableValue, extras.getSerializable(SERIALIZABLE_KEY))
        }
    }

    companion object {
        private const val STRING_KEY = "stringKey"
        private const val STRING_VALUE = "Hello, World!"
        private const val INT_KEY = "intKey"
        private const val INT_VALUE = 1
        private const val BOOLEAN_KEY = "booleanKey"
        private const val BOOLEAN_VALUE = true
        private const val LONG_KEY = "longKey"
        private const val LONG_VALUE = 123456789L
        private const val DOUBLE_KEY = "doubleKey"
        private const val DOUBLE_VALUE = 3.14
        private const val PARCELABLE_KEY = "parcelableKey"
        private const val SERIALIZABLE_KEY = "serializableKey"
    }
}

测试执行时testPutData失败,报错:

Intent extras are null
java.lang.AssertionError: Intent extras are null

问题原因

扩展函数代码中存在语法错误:

  • putData函数里的dataMap.forEach { (key, data) - 这里的-应为->,缺少右侧的>
  • put函数的when分支中,每个类型判断后的-同样应为->

这些错误导致代码逻辑未正确执行:forEach循环不会遍历map数据,putExtra也不会被调用,最终Intent的extras保持为null,测试断言失败。

解决方法

将所有错误的-替换为->,修正后的扩展函数代码如下:

import android.content.Intent
import android.os.Parcelable
import java.io.Serializable

fun Intent.addNewTaskFlags(): Intent = apply {
    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_ANIMATION)
}

fun Intent.putData(dataMap: Map<String, Any?>): Intent = apply {
    dataMap.forEach { (key, data) ->
        data?.let {
            put(key, it)
        }
    }
}

private fun Intent.put(key: String, value: Any) {
    when (value) {
        is String ->
            putExtra(key, value)
        is Int ->
            putExtra(key, value)
        is Boolean ->
            putExtra(key, value)
        is Long ->
            putExtra(key, value)
        is Double ->
            putExtra(key, value)
        is Parcelable ->
            putExtra(key, value)
        is Serializable ->
            putExtra(key, value)
        else ->
            throw IllegalArgumentException("Incompatible data type: ${value.javaClass}")
    }
}

修正后,forEach会正常遍历map中的键值对,每个数据都会被正确调用putExtra存入Intent的extras中,测试即可通过。

内容的提问来源于stack exchange,提问作者Pierre Vieira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:11:03