Skip to content

Pitest report : not existing coverage on kotlin suspend method when it is spring component #1391

@stanKluk

Description

@stanKluk

Summary

Pitest does not seem to consider main kotlin suspend methods when they are part of a spring component module.
My project uses :

  • kotlin
  • spring webflux for reactive methods
  • suspend methods
  • junit 5
  • pitest + pitest junit5 bridge

I have tried to use arcmutate plugins but the result is the same.
I have tried also to replace spring webflux by spring web.

Instructions to reproduce the problem

You can checkout this project to reproduce it : https://github.com/stanKluk/pitest-kotlin-spring-reactive-sample

Gradle configuration :

Plugins part :

plugins {
    id 'org.springframework.boot' version '2.7.18'
    id 'org.jetbrains.kotlin.jvm' version '2.0.20'
    id 'org.jetbrains.kotlin.plugin.spring' version '2.0.20'
    id 'info.solidsoft.pitest' version '1.15.0'
}

apply plugin: 'io.spring.dependency-management'
apply plugin: "info.solidsoft.pitest"

Dependencies :

dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
    implementation 'org.springframework.boot:spring-boot-starter-webflux:2.7.18'
    //same result with implementation 'org.springframework.boot:spring-boot-starter-web:2.7.18'

    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
}

Pitest plugin configuration :

pitest {
    pitestVersion = '1.18.2'
    //adds dependency to org.pitest:pitest-junit5-plugin and sets "testPlugin" to "junit5"
    junit5PluginVersion = '1.0.0'
    useClasspathFile = true
    timestampedReports = true
    detectInlinedCode = true
    targetClasses = ['com.fsk.*']
}

Class sample and its test :

@Component
class SuspendClassComponent {

    suspend fun callSomethingUseful(): Int {
        var result = 0
        val time = measureTimeMillis {
            val one = doSomethingUsefulOne()
            val two = doSomethingUsefulTwo()
            result = one + two
        }
        println("Completed in $time ms")
        return result
    }

    private suspend fun doSomethingUsefulOne(): Int {
        delay(1000L) // pretend we are doing something useful here
        return 13
    }

    private suspend fun doSomethingUsefulTwo(): Int {
        delay(1000L) // pretend we are doing something useful here, too
        return 29
    }
}

class SuspendClassTest {
    @Test
    fun `test something useful 2`() = runBlocking {
        val suspendClass = SuspendClassComponent()
        val result = suspendClass.callSomethingUseful()
        assertEquals(result, 42)
    }
}

Coverage result

As you can see below, the main suspend method is not shown in coverage report

Image

Expected result

Without the @component annotation, everything works fine

Image

And if I use @component annotation, without suspended methods, coverage is ok too

Image

Am I doing something wrong ? I'm used to use pitest for Java/Maven but after a long research I can't find what could be incorrect.
Thank you
Stan

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions