InsertKoinIO / koin

Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform
https://insert-koin.io
Apache License 2.0
9.12k stars 721 forks source link

A more Kotlin-friendly mocking framework in Koin JUnit Test #392

Closed roccadev closed 5 years ago

roccadev commented 5 years ago

Mockito is not Kotlin-friendly and it's quite a pain using it for testing: see for example the ugly `when`, or the Java-ish builder patterns or the lack of ArgumentMatcher.anyNonNull().

Furthermore, it's also a pain trying to put the right dependencies to make it work in instrumented tests for Android.

There are mocking libraries built with Kotlin and for Kotlin, like Mockk, that I'm personally using with absolute delight, that could be better in harmony with the nature of Koin. Mockk is DSL style and with its extensive usage of infix notation, it's very fluent too. It's also featured in Kotlin Academy.

I checked out the koin-test code and making the switch is really a matter of a couple of lines. However, maybe there's some better approach, like having different artifacts that use different dependencies, so that existing code with Mockito is not affected.

erickok commented 5 years ago

Mocking might be (from the Koin perspective) unneeded at all; see #379

arnaudgiuliani commented 5 years ago

@erickok interesting. And then we would avoid any mock stuff, and let people do on their own?

We would remove declareMock with just a declare function to let declare everything

erickok commented 5 years ago

Oh yes, I think a mocking framework has no place in Koin codebase, IMHO, except perhaps with some helper functions, but those should be in a different module, such that you can use koin-test without getting the dependency. Not everyone wants to use or needs a mocking framework, and some use a different one.

arnaudgiuliani commented 5 years ago

sure 👍

arnaudgiuliani commented 5 years ago

I just reworked the internals to fix many problem. Here is the new shape of mocking (without any more link to mockito):

class CoffeeMakerTest : KoinTest {

    private val coffeeMaker: CoffeeMaker by inject()
    private val heater: Heater by inject()

    @get:Rule
    val koinRule = KoinTestRule.create {
        printLogger(Level.DEBUG)
        modules(coffeeAppModule)
    }

    @get:Rule
    val mockProvider = MockProviderRule.create { clazz ->
        Mockito.mock(clazz.java)
    }

    @Test
    fun testHeaterIsTurnedOnAndThenOff() {
        declareMock<Heater> {
            given(isHot()).will { true }
        }

        coffeeMaker.brew()

        verify(heater, times(1)).on()
        verify(heater, times(1)).off()
    }
}
arnaudgiuliani commented 5 years ago

Additional work will follow in https://github.com/InsertKoinIO/koin/pull/651

Globegitter commented 5 years ago

@arnaudgiuliani I just started using koin and running into this (i.e. using mockk and want to carry on using it), any plans on when this will be released?

arnaudgiuliani commented 5 years ago

for 2.1.0, we are polishing main core features & checking blocking issues We will publish intermediate versions, or perhaps split the content to not wait to much to your feedback also :)