Ignore Kotlin "!!." operator

94 views
Skip to first unread message

fate...@gmail.com

unread,
Dec 22, 2018, 2:30:45 PM12/22/18
to JaCoCo and EclEmma Users
Is it possible to ignore !!. operator in Kotlin code when calculating test coverage? Sometimes I have a nullable variable which cannot be null in a lifecycle method, and if I use !!., then jacoco report says "1 of 2 branches missed". I don't know how to handle that easily

Evgeny Mandrikov

unread,
Dec 25, 2018, 6:49:15 PM12/25/18
to JaCoCo and EclEmma Users
Hi,

On Saturday, December 22, 2018 at 8:30:45 PM UTC+1, fate...@gmail.com wrote:
Is it possible to ignore !!. operator in Kotlin code when calculating test coverage? Sometimes I have a nullable variable which cannot be null in a lifecycle method, and if I use !!., then jacoco report says "1 of 2 branches missed". I don't know how to handle that easily

If variable cannot be null, then why it is declared as nullable?


Regards,
Evgeny

fate...@gmail.com

unread,
Dec 26, 2018, 2:14:32 PM12/26/18
to JaCoCo and EclEmma Users
E.g. a jpa entity has a nullable field ID to be able to be saved. If I request the entity from a repository which returns only saved entities, then I have to use !!. operator to reference id values.
Generally, such cases often occur when dealing with lifecycle-dependent objects. I usually set a variable nullable to:
* to force programmers to pay attention when using it
* to make it possible to release memory by nullifying the variable

raviki...@gmail.com

unread,
Jan 4, 2019, 5:44:00 PM1/4/19
to JaCoCo and EclEmma Users

Yeah this is a valid one.
Even if we write a test that throws NPE, still it shows "1 of 2 branches missed".

raviki...@gmail.com

unread,
Jan 4, 2019, 6:01:37 PM1/4/19
to JaCoCo and EclEmma Users

Here is an example:

Say we have a piece of code like this

fun getMapValue(map: Map<String, Int?>, key: String): Int {
return map[key]!!
}
The possible tests that we can write for this are:

@Test
fun `verify getMapValue returns map value for a valid key`() {
val map = mapOf("a" to 1, "b" to 2)
val result = TestJacocoBranchCoverage().getMapValue(map, "a")
Assertions.assertEquals(result, 1)
}

@Test
fun `verify getMapValue throws NPE for an invalid key`() {
val map = mapOf("a" to 1, "b" to 2)
assertThrows<NullPointerException> { TestJacocoBranchCoverage().getMapValue(map, "c") }
}

map[key]!! this means return the value if not null else throw null pointer exception. So both the test should ideally cover the whole code.

But Jacoco still complaints about a missing branch.

Evgeny Mandrikov

unread,
Jan 4, 2019, 7:22:31 PM1/4/19
to JaCoCo and EclEmma Users
Ravkiran, your example can be reduced to

private fun example(x: Any?) {
    x!!
}

fun main(args: Array<String>) {
    example("")
    try {
        example(null)
    } catch (e: NullPointerException) {
    }
}

Anyway thank you both for these valuable inputs!

Inability to cover case of exception seems to be related to widely known JaCoCo limitation - see for example https://stackoverflow.com/a/54034393/244993 that refers to https://www.jacoco.org/jacoco/trunk/doc/faq.html "Source code lines with exceptions show no coverage. Why?" , because

x!!

compiles into something like

if (x == null) kotlin.jvm.internal.Intrinsics.throwNpe()

So even if one can question whether this branch needs to be tested or not (and hence shown as covered or not), as of now due to above limitation anyway seems better to implement filter - https://github.com/jacoco/jacoco/pull/802


Regards,
Evgeny

Evgeny Mandrikov

unread,
Jan 5, 2019, 1:05:51 AM1/5/19
to JaCoCo and EclEmma Users
Reply all
Reply to author
Forward
This conversation is locked
You cannot reply and perform actions on locked conversations.
0 new messages