结合null安全性和assertNotNull

Fee*_*eco 11 kotlin kotlin-null-safety

在测试中我们通常有assertNotNull,但它不执行从可空类型到非可空类型的智能转换.我必须写这样的东西:

if (test == null) {
    Assert.fail("")
    return
}
Run Code Online (Sandbox Code Playgroud)

这是一个仅通过assertNotNull调用执行智能转换的解决方法吗?你如何解决?

hot*_*key 9

不幸的是,您调用的函数体(包括内联函数)不用于智能强制转换和可空性推理.

你的代码中没有太多东西可以改进,我只建议一件事:你可以使用Elvis运算符Nothing那些断言语句的函数.控制流分析考虑了由此产生的分支Nothing并从中推断出可空性:

fun failOnNull(): Nothing = throw AssertionError("Value should not be null")
Run Code Online (Sandbox Code Playgroud)

val test: Foo? = foo()

test ?: failOnNull()
// `test` is not-null after that
Run Code Online (Sandbox Code Playgroud)

这也可以在没有函数的情况下编写:test ?: throw AssertionError("...")因为throw表达式也有类型Nothing.


说到断言失败的更一般情况,可以使用一个fail(...): Nothing函数,它也为控制流分析提供了额外的提示.JUnit Assert.fail(...)不是一个Nothing函数,但您可以在kotlin-test-junit模块中找到一个函数或编写自己的函数.

test as? SomeType ?: fail("`test` should be an instance of SomeType")
// smart cast works here, `test` is `SomeType`
Run Code Online (Sandbox Code Playgroud)


Rol*_*f ツ 7

kotlin.test库为此提供了一个简单的解决方案:

kotlin.test.assertNotNull()

由于此函数实现了 Kotlin 合约,因此它支持智能转换:

contract { returns() implies (actual != null) }

例子:

    fun Foo?.assertBar() {
        assertNotNull(this)
        assertEquals(this.bar, 0)
    }
Run Code Online (Sandbox Code Playgroud)

只要确保使用正确的assertNotNull导入 ( import kotlin.test.assertNotNull) 即可!

如果您尚未使用该kotlin.test库,请将其添加到您的项目中:

group: 'org.jetbrains.kotlin', name: 'kotlin-test', version: '1.3.11