结合null安全性和assertNotNull

时间:2017-02-05 03:32:47

标签: kotlin kotlin-null-safety

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

if (test == null) {
    Assert.fail("")
    return
}

仅通过assertNotNull调用执行智能投射是一种解决方法吗?你是如何处理它的?

3 个答案:

答案 0 :(得分:9)

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

您的代码中没有太多可以改进的地方,我只建议一件事:您可以将the Elvis operatorNothing函数一起用于这些断言语句。控制流分析将Nothing中的分支考虑在内,并从中推断出可为空性:

fun failOnNull(): Nothing = throw AssertionError("Value should not be null")

val test: Foo? = foo()

test ?: failOnNull()
// `test` is not-null after that

这也可以在没有函数的情况下编写: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`

答案 1 :(得分:0)

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

kotlin.test.assertNotNull()

由于此功能实现了Kotlin合同,因此支持智能投射:

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

示例:

    fun Foo?.assertBar() {
        assertNotNull(this)
        assertEquals(this.bar, 0)
    }

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

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

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

答案 2 :(得分:0)

非常感谢@Rolf指出assertNotNull库在其答案kotlin-test中提供的here方法。

我只想添加并指出此方法具有非空返回类型(即它返回作为非空对象传递给它的可空对象)。因此,如果您要在测试中强制展开属性,则可以远离此属性并按如下所示改进测试:

val myProperty = assertNotNull(myObject?.myProperty)
assertEquals("Foo", myProperty.someOtherProperty)