Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use declareMock to override a dependency in Kotest #2051

Open
mityakoval opened this issue Nov 8, 2024 · 0 comments
Open

Unable to use declareMock to override a dependency in Kotest #2051

mityakoval opened this issue Nov 8, 2024 · 0 comments
Labels

Comments

@mityakoval
Copy link

mityakoval commented Nov 8, 2024

Describe the bug
In a Ktor server the single injected with a declareMock method in testApplication in a KoinTest/Kotest test doesn't override the service in main package.

class ApplicationTest : FunSpec(), KoinTest {


    override fun extensions(): List<Extension> = listOf(
        KoinExtension(
            module = module {},
            mockProvider = {
                mockkClass(it)
            },
            mode = KoinLifecycleMode.Root
        )
    )

    init {
        val appConfig = listOf(
            ApplicationConfig("application.test.conf")
        ).reduce(ApplicationConfig::mergeWith)

        test("Test mock injection") {
            testApplication {
                environment {
                    config = appConfig
                }

                application {
                    val serviceBMock = declareMock<ServiceB>()

                    every { serviceBMock.identify() }.returns("Mock")
                }

                val cli = createClient {
                    install(ContentNegotiation) {
                        json()
                    }
                }

                val resp = cli.get("/test")
                val body = resp.body<Response>()
                body.a shouldBe "ServiceA"
                body.b shouldBe "Mock"

            }
        }
    }
}

Noticed that this issue is arising if there's a somewhat complicated routing setup (see reproduction repo for more details):

fun Application.configureRouting() {
    testRouting()
}

...

fun Application.testRouting() {
    routing {
        val serviceA by inject<ServiceA>()
        val serviceB by inject<ServiceB>()
        test(serviceA, serviceB)
    }
}

@Serializable
data class Response(val a: String, val b: String)


fun Route.test(serviceA: ServiceA, serviceB: ServiceB) {
    get("/test") {
        call.respond(status = HttpStatusCode.OK, Response(serviceA.identify(), serviceB.identify()))
    }
}

To Reproduce
Here's a repo with a sample project that reproduces this issue: https://github.com/mityakoval/KoinKotestSample

Just run ApplicationTest suite there

Expected behavior
I expected the declareMock method to inject the object created by Mockk in to Koin to be used in test instead of the service declared in the main application.

Koin module and version:
koin-ktor:4.0.0
koin-test:4.0.0
Ktor:2.3.12
kotest-runner-junit5:5.9.1
kotest-extensions-koin:1.3.0

Snippet or Sample project to help reproduce
Sample project to reproduce: https://github.com/mityakoval/KoinKotestSample

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants