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
相关产品推荐
相关产品推荐

