Search code examples
kotlinmicronaut

How do I use TestPropertyProvider and inject RxHttpClient with Micronaut using Kotlin


Note - I'm a Java+Spring guy trying out Kotlin+Micronaut.

I'm trying to use the TestPropertyProvider to set properties after my embedded service starts.
It works ok, as long as there are no constructor parameters in my test class.

I can add the RxHttpClient as a constructor parameter and it gets injected fine.

But, I'd like to inject the RxHttpClient from Micronaut and also implement TestPropertyProvider.
I tried adding @Inject to the RxHttpClient but get the error This annotation is not applicable to target 'local variable' [because the test body is a lambda passed to the superclass]

Without the @Inject I get the error lateinit property client has not been initialized

My base class has the TestPropertyProvider implementation .

abstract class ZeebeSpecification(body: AbstractStringSpec.() -> Unit): StringSpec(body), TestPropertyProvider {
    override fun getProperties(): MutableMap<String, String> {
        return mutableMapOf("orchestrator.management.client.brokerContactPoint" to IntegrationTestHarness.instance.getBroker())
    }
}

TestPropertyProvider works, but RxHttpClient not injected

@MicronautTest
class ZeebeBroker1Test() : ZeebeSpecification({

    @Client("/") lateinit var client: RxHttpClient;

    ...tests

}) {}

RxHttpClient injected, but TestPropertyProvider not evaluated

@MicronautTest
class ZeebeBroker1Test(@Client("/" val client: RxHttpClient) : ZeebeSpecification({


    ...tests

}) {}

I removed the base class from the equation and made my test directly implement the TestPropertyProvider but it still fails.

@MicronautTest
class ZeebeBroker1Test(@Client("/") var client: HttpClient) : BehaviorSpec(), TestPropertyProvider {

    init {
        ...tests
    }
    private fun getBroker(): String {
        return IntegrationTestHarness.instance.getBroker()
    }
    override fun getProperties(): MutableMap<String, String> {
        return mutableMapOf("orchestrator.management.client.brokerContactPoint" to getBroker())
    }
}

Seems like it's the same issue as this, but I'm already using v1.1.2
https://github.com/micronaut-projects/micronaut-test/issues/82

If I tried to use @Inject @Client("/") client: RxHttpClient it would throw the error message: Missing bean argument [LoadBalancer loadBalancer] for type: io.micronaut.http.client.DefaultHttpClient. Required arguments: LoadBalancer

How do I use both TestPropertyProvider and injected RxHttpClient?


Solution

  • I resolved the issue by moving the body of the spec into the init, and injecting the RxHttpClient as a field.

    @MicronautTest
    class ZeebeBroker1Test() : ZeebeSpecification() {
    
        @Inject @field:Client("/") lateinit var client: RxHttpClient
    
        private val log: Logger = LoggerFactory.getLogger(ZeebeBroker1Test::class.java)
    
        init {
            "test case 1" {
                ...
            }
    
            "test case 2" {
                ...
            }
        }
    }
    

    And I let the base class implement the TestPropertyProvider interface .

    abstract class ZeebeSpecification(): StringSpec(), TestPropertyProvider {
    
        open fun getBroker(): String {
            return IntegrationTestHarness.instance.getBroker()
        }
    
        override fun getProperties(): MutableMap<String, String> {
            return mutableMapOf("orchestrator.management.client.brokerContactPoint" to getBroker())
        }
    }