4

I am using the PostgreSQL database in my Ktor Project. I saved JDBC_URL, JDBC_DRIVER..., in system environment variables of Intellij Idea.

    fun hikari(): HikariDataSource{
    val config = HikariConfig()
    ****config.driverClassName =  System.getenv("JDBC_DRIVER")***********
    ****config.jdbcUrl = System.getenv("JDBC_DATABASE_URL")*************
    config.maximumPoolSize = 3
    config.isAutoCommit = false
    config.transactionIsolation = "TRANSACTION_REPEATABLE_READ"
    val password = System.getenv("DB_PASSWORD")
    if(password != null){
        config.password = password
    }
    config.validate()

    return HikariDataSource(config)
}

Everything works fine. But while automated testing it is giving NULL POINTER EXCEPTION while accessing these environments variables

Testing function:

    @Test
fun testUserLogin_wrongPassword_false(){
    withTestApplication({
        module(testing = true)
    }) {
        handleRequest(HttpMethod.Post,"/v1/users/login"){
            addHeader("Content-Type","application/json")
            setBody("""{"email": "temp","password": "temp"}""")
        }.apply {
            assertEquals(HttpStatusCode.BadRequest,response.status())
        }
    }
}

Exception:

java.lang.NullPointerException
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at com.zaxxer.hikari.HikariConfig.attemptFromContextLoader(HikariConfig.java:899)
at com.zaxxer.hikari.HikariConfig.setDriverClassName(HikariConfig.java:474)
at com.example.repository.DatabaseFactory.hikari(DatabaseFactory.kt:40)
at com.example.repository.DatabaseFactory.init(DatabaseFactory.kt:21)
at com.example.ApplicationKt.module(Application.kt:41)
at com.example.ApplicationTest$testUserLogin_wrongPassword_false$1.invoke(ApplicationTest.kt:31)
at com.example.ApplicationTest$testUserLogin_wrongPassword_false$1.invoke(ApplicationTest.kt:17)
at io.ktor.server.testing.TestEngineKt$withTestApplication$1.invoke(TestEngine.kt:67)
at io.ktor.server.testing.TestEngineKt$withTestApplication$1.invoke(TestEngine.kt)
at io.ktor.server.testing.TestEngineKt.withApplication(TestEngine.kt:49)
at io.ktor.server.testing.TestEngineKt.withApplication$default(TestEngine.kt:43)
at io.ktor.server.testing.TestEngineKt.withTestApplication(TestEngine.kt:66)
at com.example.ApplicationTest.testUserLogin_wrongPassword_false(ApplicationTest.kt:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:119)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.lang.Thread.run(Thread.java:745)

How can we access environment variables while testing or is there any other method to test while using database?

Samarth Gupta
  • 61
  • 1
  • 5

3 Answers3

0

You can either introduce an additional level of abstraction for accessing the environment variables (by making a parameter for hikari function and then passing through the argument for it in tests) or globally mutate required environment variables before each test (https://stackoverflow.com/a/40682052/13963150). Also, you can use mocking for the whole HikariDataSource.

Aleksei Tirman
  • 4,658
  • 1
  • 5
  • 24
0

In tests, instead of using an application.conf to define configuration properties, you can use the MapApplicationConfig.put method:

withTestApplication({
(environment.config as MapApplicationConfig).apply {
    // Set here the properties
    put("youkube.session.cookie.key", "03e156f6058a13813816065")
    put("youkube.upload.dir", tempPath.absolutePath)
}
main() // Call here your application's module
})

https://ktor.io/docs/testing.html#defining-configuration-properties-in-tests

Isoq Hakimov
  • 118
  • 1
  • 1
  • 7
  • First of all, Thanks for the reply. I have seen that method but it is for configuration properties, but I'm asking for environment variables. How can I pass environment variables in it. – Samarth Gupta Mar 17 '21 at 16:38
-1

When using System.getEnv() the best option I see is to add those environment variables in the Gradle test properties

build.gradle.kts

...
tasks{...}

tasks.test {
  environment("DB_PASSWORD", "1234_test")
  environment("DB_NAME", "my_db")

}

dependencies ...

Based on Ktor 2.2.3 - Referece - Test an application with Customize environment

    @Test
    fun test() = testApplication {

        environment {
            config = MapApplicationConfig("ktor.environment" to "dev")
        }
        ....
    }
JPilson
  • 1,075
  • 11
  • 10