我正在尝试为一些Android代码编写单元测试,以查找Intent
对象中存在的特定键。作为测试的一部分,我将创建一个Intent
对象,并向其中添加一个字符串。但是,当我使用以下代码时,我的变量被初始化为null:
val data = Intent().putExtra("key", "value")
// data is null
如果我将其分成两行,则效果很好:
val data = Intent()
data.putExtra("key", "value")
// data is non-null and contains my key/value
Kotlin语言的什么功能导致这种情况发生?
请注意,putExtra()
返回一个Intent
对象。来自Android来源:
public @NonNull Intent putExtra(String name, String value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putString(name, value);
return this;
}
在第一种情况下,推断的类型为Intent!
。我给人的印象是,这仅表示它是Intent
或Intent?
,但Kotlin不想让开发人员对Java平台类型发狂。尽管如此,鉴于putExtra()
返回的是非空值,我希望data
的实际值为非空。
答案 0 :(得分:1)
简短的答案是@CommonsWare和@TheWanderer在评论中提到的内容:我的测试类位于test/
目录中,因此它使用的是模拟Intent
实现而不是真实的实现。
当我将测试移到androidTest/
目录时,一切都会按预期进行。观察到的行为与Kotlin无关。
关于为什么如此令人困惑的一些额外信息...
首先,我在写这篇文章时弄错了:
val data = Intent() data.putExtra("key", "value") // data is non-null and contains my key/value
data
变量 为非空,但实际上并未包含我的键/值对。我正在使用的模拟Intent
实现放弃了putExtra()
调用。
那么,为什么我的考试通过了?
我决定要深入研究的一个特定测试是测试否定情况(当Intent
中出现了它期望的其他键时)。但是我没有传递带有错误键的Intent,而是传递没有键的Intent。但是,无论哪种方式,预期的密钥都不存在,并且该方法返回false
。
肯定的情况(实际上所需的密钥已传递给putExtra()
)以AssertionError
失败。太糟糕了,我没有选择对此进行审查。
我的主项目显然已通过Intent.putExtra()
gradle选项将returnDefaultValues = true
设置为无操作。当我创建一个新项目并尝试重现此问题时,我得到一个非常明显的错误:
java.lang.RuntimeException: Method putExtra in android.content.Intent not mocked. See http://g.co/androidstudio/not-mocked for details. at android.content.Intent.putExtra(Intent.java) at com.example.stackoverflow.IntentTest.test(IntentTest.kt:12)
不幸的是,在嘲笑putExtra()
的情况下,我从未收到过此有用的消息。