Объединение нулевой безопасности и assertNotNull

В тесте у нас обычно есть assertNotNull, но он не выполняет интеллектуальный приведение от нулевого типа к не-nullable. Я должен написать что-то вроде этого:

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

Это обходное решение для выполнения интеллектуального приведения только при вызове assertNotNull? Как вы справляетесь с этим?

Ответ 1

К сожалению, тела функций, которые вы вызываете, включая встроенные функции, не используются для умных приведений и выводов обнуляемости.

В вашем коде мало что можно улучшить, и я хотел бы предложить только одно: вы можете использовать оператор Элвиса с функцией Nothing для этих утверждений. Анализ потока управления учитывает ответвления, возникающие в 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'

Ответ 2

Библиотека 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