https://kotlinlang.org logo
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
benchmarks
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
confetti
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hiring-french
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
lincheck
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by
Title
r

ram prasad

06/28/2022, 7:50 AM
Hello Team, Newbie to Kotlin and Ktor. I need help in adding unit tests which uses a testing database. Is there a reference that I can follow. I'm using Ktor
2.0.2
. Basically I need to understand the setup(connection to test db and create data for testing) and teardown(cleanup of test data after all tests) parts using the
testApplication
Thanks in advance!
a

Aleksei Tirman [JB]

06/28/2022, 3:33 PM
You can use the
TestApplicationEngine
class and setup/tear down functionality of a test framework to solve your problem. Here is an example with MongoDB:
import com.mongodb.client.MongoClient
import com.mongodb.client.MongoDatabase
import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.testing.*
import io.ktor.test.dispatcher.*
import org.junit.After
import org.junit.AfterClass
import org.junit.BeforeClass
import org.litote.kmongo.KMongo
import org.litote.kmongo.getCollection
import kotlin.test.Test
import kotlin.test.assertEquals

class DBTest {
    companion object {
        private lateinit var server: TestApplicationEngine
        private lateinit var mongoClient: MongoClient
        private lateinit var db: MongoDatabase
        private val httpClient: HttpClient get() = server.client

        @BeforeClass
        @JvmStatic
        fun setup() {
            mongoClient = KMongo.createClient()
            db = mongoClient.getDatabase("test")

            server = TestApplicationEngine(createTestEnvironment {
                developmentMode = false // to prevent a bug with a class loader in Ktor 2.0.2
                module {
                    routes(db)
                }
            })

            server.start(wait = false)
        }

        @AfterClass
        @JvmStatic
        fun tearDown() {
            server.stop()
            mongoClient.close()
        }
    }

    @After
    fun dropCollection() {
        db.getCollection<Name>().drop()
    }

    @Test
    fun checkSomeNames() = testSuspend {
        db.getCollection<Name>().insertMany(
            listOf(
                Name("John"),
                Name("Mike"),
                Name("Eddie"),
            )
        )

        assertEquals("John,Mike,Eddie", httpClient.get("/").bodyAsText())
    }

    @Test
    fun checkNoNames() = testSuspend {
        assertEquals("", httpClient.get("/").bodyAsText())
    }
}

fun Application.routes(db: MongoDatabase) {
    routing {
        get("/") {
            val collection = db.getCollection<Name>()
            val names = collection.find().toList()

            call.respondText {
                names.joinToString(separator = ",") { it.value }
            }
        }
    }
}

data class Name(val value: String)
r

ram prasad

06/29/2022, 4:40 AM
Thanks @Aleksei Tirman [JB]. I'll cheeck this out
Appreciate the help 🙂
Hi @Aleksei Tirman [JB], Got the tests working with connection to test_database. But for the UserTests to pass, we need ApplicationTest to be called first which is expected but this might not work with tests running in parallel.
BaseTest.kt
-----------

object BaseTest {
  private lateinit var server: TestApplicationEngine
  lateinit var db: Database
  val httpClient: HttpClient get() = server.client

  fun setup() {
    server = TestApplicationEngine(createTestEnvironment {
      developmentMode = false // to prevent a bug with a class loader in Ktor 2.0.2
      module {
        configureRouting()
        configureSerialization()
        db = DbFactory.init()
      }
    })

    server.start(wait = false)
  }
}

ApplicationTest.kt
-------------------

class ApplicationTest {
  @Test
  fun init() {
    BaseTest.setup()
  }
}


UserTest.kt
------------

class UserTest {
  companion object {
    @AfterClass
    @JvmStatic
    fun purgeData() {
      transaction(DbTest.db) { UserTable.deleteWhere { UserTable.id eq 4 }}
    }
  }

  @Test
  fun testRoot() = testSuspend() {
    val response = <http://DbTest.httpClient.post|DbTest.httpClient.post>("/api/v1/users") {
      contentType(ContentType.Application.Json)
      setBody(
        Gson().toJson(mockUser())
      )
    }

    assertEquals(HttpStatusCode.Created, response.status)
  }

  private fun mockUser(): UserCreateModel {
    return UserCreateModel(
      "4",
      "Ram",
      "<mailto:ram619prasad@sam.com|ram619prasad@sam.com>",
      "testPassword",
      "7382119086"
    )
  }
}
Is there a proper way to have the dbconnection, creation of test httpClient and etc so that the same can be re-used by multiple test files rather than ensuring our ApplicationTest runs first and then later the rest of the many test files.