Could not create instance of functional test class. Specs must have a public zero-arg constructor

960 Views Asked by At

I am working with Kotlin, Micronaut and Kotest5. Setup a functional test directory in gradle. Created functional test in it. Test runs fine, however if I am injecting objects in the test class constructor I am getting this error: Could not create instance of class. Specs must have a public zero-arg constructor.

If I move this test class into the test directory instead of the custom setup functional test directory. And I added io.kotest.provided package with a class in it, here is the class

import io.kotest.core.config.AbstractProjectConfig
import io.micronaut.test.extensions.kotest5.MicronautKotest5Extension

object ProjectConfig : AbstractProjectConfig() {
    override fun extensions() = listOf(MicronautKotest5Extension)
}

The test runs with no issue! If I remove this ProjectConfig class, the same issue comes back. However if I move everything back to the functional test directory even with this ProjectConfig class, it still does not work. It is like it can not pick up this extension configuration.

Everything like @MicronautTest, classpath, runtimeClasspath are all set properly. When running tests with injected objects in functional test directory, it just kept giving me that Specs must have a public zero-arg constructor. error.

Does anyone know how to fix this extension configuration not being picked up by the functional tests issue?

2

There are 2 best solutions below

1
Tech Noob On BEST ANSWER

After digging through all the documents and trying out all the things I found. It seems that adding a micronuat.inject as functionalTest annotation processor fixed the issue. I am not sure why this is not needed by the default test, and while I pointed everything for functional test to default test, it should have everything that is available to the default thats available to the functional test, but seems like annotation processor is not included in this case.

0
Rob Schwartz On

I have the same exact idea, except my test suite is called integrationTest. I had to tell micronaut about the extra source set like so

micronaut {
    runtime("netty")
    testRuntime("kotest")
    processing {
        incremental(true)
        annotations("com.example")
        additionalSourceSets.add(sourceSets.getByName("integrationTest")) //add additional integration testing sources set
    }
}

And my problem was fixed! Also note that this micronaut DSL section needs to be below the test suites DSL section.

Explanation

While digging into the problem I noticed the dependency trees were different between the test suite classpaths when I expected them to be the same (outside of the one dependency that is added for integration tests). Searching through the micronaut gradle plugin docs you can see there is a note

// additional sourceSets can be configured here to apply the BOM
// and annotation processors to source sets other than 'main'

Both of those points are big keys, and after telling micronaut about the additional source set, the BOM and annotation processing is applied and the dependency trees match!