Lucas
Lucas

Reputation: 776

How to create an ApplicationContext for tests in kotlin?

I have been struggling to start an application context during tests so I can inject bean at run-time but it seems I can't get the ApplicationContext wired here is what I am trying

  package com.wayfair.samworkgroupsservice.adapter

import io.r2dbc.mssql.MssqlConnectionConfiguration
import io.r2dbc.mssql.MssqlConnectionFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.config.ConstructorArgumentValues
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.beans.factory.support.GenericBeanDefinition
import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.Configuration
import org.springframework.data.r2dbc.core.DefaultReactiveDataAccessStrategy
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate
import org.springframework.data.r2dbc.dialect.SqlServerDialect
import org.springframework.r2dbc.core.DatabaseClient
import org.springframework.test.context.ContextConfiguration

@Configuration
@ContextConfiguration("classpath:/testContext.xml")
class TemplateFactory {
    @Autowired
    lateinit var applicationContext: ApplicationContext

    private val beanFactory: BeanDefinitionRegistry =
        applicationContext.autowireCapableBeanFactory as BeanDefinitionRegistry

    fun registerTemplateBean(host: String, port: Int) {
        val beanDefinition = GenericBeanDefinition()
        beanDefinition.beanClass = R2dbcEntityTemplate::class.java
        val args = ConstructorArgumentValues()
        args.addIndexedArgumentValue(
            0,
            DatabaseClient.builder()
                .connectionFactory(connectionFactory(host, port))
                .bindMarkers(SqlServerDialect.INSTANCE.bindMarkersFactory)
                .build()
        )
        args.addIndexedArgumentValue(1, DefaultReactiveDataAccessStrategy(SqlServerDialect.INSTANCE))

        beanDefinition.constructorArgumentValues = args
        beanFactory.registerBeanDefinition("R2dbcEntityTemplate", beanDefinition)
    }

//    fun entityTemplate(host: String = "localhost", port: Int = 1435) =
//        R2dbcEntityTemplate(
//            DatabaseClient.builder()
//                .connectionFactory(connectionFactory(host, port))
//                .bindMarkers(SqlServerDialect.INSTANCE.bindMarkersFactory)
//                .build(),
//            DefaultReactiveDataAccessStrategy(SqlServerDialect.INSTANCE)
//        )

    private fun connectionFactory(host: String, port: Int) =
        MssqlConnectionFactory(
            MssqlConnectionConfiguration.builder()
                .host(host)
                .port(port)
                .username("sa")
                .password("Password123@#?")
                .build()
        )
}

here is my testContext.xml (it is empty for now because I want to inject beans at run time):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    
</beans>

Does anyone know why I get the following error?

lateinit property applicationContext has not been initialized
kotlin.UninitializedPropertyAccessException: lateinit property applicationContext has not been initialized

Thank you in advance )

Upvotes: 4

Views: 392

Answers (0)

Related Questions