我有以下 Android Intent 扩展:
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
为什么会发生这种情况以及如何解决?
我想这种行为的原因已在here进行了描述。
但是,本地测试不能使用
或其任何方法,因为它们属于Android框架。Context
在你的情况下,
Intent
没有被嘲笑。
您可能正在使用
unitTests.returnDefaultValues = true
,因为您没有收到 Method putExtra in android.content.Intent not mocked 错误。但通过此配置,putExtra
不执行任何操作,并且 extras
为 null,从而产生 AssertionError
。
我认为您可以考虑测试扩展函数本身的行为,而不是测试它们调用的间接结果(即
extras
中的 Intent
属性)。事实上,putExtras
修改extras
属性是Intent
内部实现的一部分,因此是对Intent
类进行测试的问题。但对于这些扩展函数的测试,重要的是如何准确地调用这些 Intent
方法 - 例如调用了多少次,用什么参数调用,而不是进一步的影响,这就是隔离的意义。