Kotlin-为什么初始化后此变量为null?

时间:2019-01-10 20:12:42

标签: android kotlin

我正在尝试为一些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!。我给人的印象是,这仅表示它是IntentIntent?,但Kotlin不想让开发人员对Java平台类型发狂。尽管如此,鉴于putExtra()返回的是非空值,我希望data的实际值为非空。

1 个答案:

答案 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()的情况下,我从未收到过此有用的消息。