2

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?

Tech Noob
  • 510
  • 1
  • 9
  • 33

2 Answers2

1

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!

Rob Schwartz
  • 192
  • 1
  • 12
0

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.

Tech Noob
  • 510
  • 1
  • 9
  • 33
  • Did you add your new source set to the micronaut gradle plugin extension? The plugin automatically configures micronaut inject on the main source set which is why you don't need to declare it yourself. If you add the new source set as shown, that dependency will also be configured on the new source set without you needing to declare it. – Rob Schwartz Jun 12 '23 at 15:22