Skip to content

Commit

Permalink
Add test for :di-kodein-advanced, including one with overridden depen…
Browse files Browse the repository at this point in the history
…dency.
  • Loading branch information
TWiStErRob committed Feb 15, 2020
1 parent 0e2a507 commit 89ea9b6
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 22 deletions.
47 changes: 25 additions & 22 deletions other/di-kodein-advanced/src/KodeinAdvancedApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import io.ktor.server.netty.*
import kotlinx.html.*
import org.kodein.di.*
import org.kodein.di.generic.*
import java.util.*

/**
* Entry point of the embedded-server sample program:
Expand All @@ -27,18 +26,22 @@ import java.util.*
fun main(args: Array<String>) {
embeddedServer(Netty, port = 8080) {
kodeinApplication { application ->
application.apply {
// This adds automatically Date and Server headers to each response, and would allow you to configure
// additional headers served to each response.
install(DefaultHeaders)
}

bindSingleton { Users.Repository() }
bindSingleton { Users.Controller(it) }
advancedApplication(application)
}
}.start(wait = true)
}

internal fun Kodein.MainBuilder.advancedApplication(application: Application) {
application.apply {
// This adds automatically Date and Server headers to each response, and would allow you to configure
// additional headers served to each response.
install(DefaultHeaders)
}

bind<Users.IRepository>() with singleton { Users.Repository() }
bind<Users.Controller>() with singleton { Users.Controller(kodein) }
}

/**
* Users Controller, Router and Model. Can move to several files and packages if required.
*/
Expand All @@ -52,7 +55,7 @@ object Users {
/**
* [Repository] instance provided by [Kodein]
*/
val repository: Repository by instance()
private val repository: IRepository by instance()

/**
* Registers the routes related to [Users].
Expand Down Expand Up @@ -94,16 +97,23 @@ object Users {
data class User(val name: String)

/**
* [Users.Repository] that will handle operations related to the users on the system.
* Repository that will handle operations related to the users on the system.
*/
interface IRepository {
fun list() : List<User>
}

/**
* Fake in-memory implementation of [Users.IRepository] for demo purposes.
*/
class Repository {
class Repository : IRepository {
private val initialUsers = listOf(User("test"), User("demo"))
private val usersByName = LinkedHashMap<String, User>(initialUsers.associateBy { it.name })
private val usersByName = initialUsers.associateBy { it.name }

/**
* Lists the available [Users.User] in this repository.
*/
fun list() = usersByName.values.toList()
override fun list() = usersByName.values.toList()
}

/**
Expand Down Expand Up @@ -174,7 +184,7 @@ abstract class KodeinController(override val kodein: Kodein) : KodeinAware {
/**
* Injected dependency with the current [Application].
*/
val application: Application by instance()
private val application: Application by instance()

/**
* Shortcut to get the url of a [TypedRoute].
Expand All @@ -187,13 +197,6 @@ abstract class KodeinController(override val kodein: Kodein) : KodeinAware {
abstract fun Routing.registerRoutes()
}

/**
* Shortcut for binding singletons to the same type.
*/
inline fun <reified T : Any> Kodein.MainBuilder.bindSingleton(crossinline callback: (Kodein) -> T) {
bind<T>() with singleton { callback(this@singleton.kodein) }
}

/**
* Interface used for identify typed routes annotated with [Location].
*/
Expand Down
93 changes: 93 additions & 0 deletions other/di-kodein-advanced/test/KodeinAdvancedApplicationTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package io.ktor.samples.kodein

import io.ktor.http.HttpMethod
import io.ktor.http.HttpStatusCode
import io.ktor.server.testing.withTestApplication
import org.kodein.di.generic.bind
import org.kodein.di.generic.singleton
import kotlin.test.Test
import kotlin.test.assertEquals

/**
* Integration tests for the [advancedApplication] module from KodeinAdvancedApplication.
*/
class KodeinAdvancedApplicationTest {

@Test
fun `get user`() = withTestApplication<Unit>(
{
kodeinApplication { advancedApplication(it) }
}
) {
handleRequest { method = HttpMethod.Get; uri = "/users/fake" }.apply {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals(
"""
<!DOCTYPE html>
<html>
<body>
<h1>fake</h1>
</body>
</html>
""".trimIndent() + "\n",
response.content
)
}
}

@Test
fun `get default users`() = withTestApplication<Unit>(
{
kodeinApplication { advancedApplication(it) }
}
) {
handleRequest { method = HttpMethod.Get; uri = "/users/" }.apply {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals(
"""
<!DOCTYPE html>
<html>
<body>
<ul>
<li><a href="/users/test">test</a></li>
<li><a href="/users/demo">demo</a></li>
</ul>
</body>
</html>
""".trimIndent() + "\n",
response.content
)
}
}

// Note: a JVM bug prevents us from using `nice test names` when there's a local class defined in it.
@Test
fun testGetFakeUsers() = withTestApplication<Unit>(
{
class FakeRepository : Users.IRepository {
override fun list() = listOf(Users.User("fake"))
}
kodeinApplication {
advancedApplication(it)
bind<Users.IRepository>(overrides = true) with singleton { FakeRepository() }
}
}
) {
handleRequest { method = HttpMethod.Get; uri = "/users/" }.apply {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals(
"""
<!DOCTYPE html>
<html>
<body>
<ul>
<li><a href="/users/fake">fake</a></li>
</ul>
</body>
</html>
""".trimIndent() + "\n",
response.content
)
}
}
}

0 comments on commit 89ea9b6

Please sign in to comment.