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

merge inject and declareMock #243

Closed
dpreussler opened this issue Sep 24, 2018 · 5 comments
Closed

merge inject and declareMock #243

dpreussler opened this issue Sep 24, 2018 · 5 comments
Labels
status:checking currently in analysis - discussion or need more detailed specs test
Milestone

Comments

@dpreussler
Copy link

dpreussler commented Sep 24, 2018

Is your feature request related to a problem? Please describe.
I don't like that declareMock is separate from the definition of the mock.
I normally try to do both in one call since Kotlin makes it so easy:

  val useCase = mock<LeaguesUseCase>().apply {
        whenever(getTeams()).thenReturn(Single.just(emptyList()))
    }

it' even better with Kotlin-Mockito:

  val useCase = mock<LeaguesUseCase> {
        on{ getTeams() } doReturn Single.just(emptyList())
    }

Describe the solution you'd like
My idea would be sth similar to that approach.

inline fun <reified T: Any> KoinTest.mock(
    name: String = "",
    noinline parameters: ParameterDefinition = emptyParameterDefinition(),
    crossinline stubbing: T.() -> Unit = {}
) = lazy {
    declareMock<T>()
    getKoin().get<T>(name, parameters).also {
        stubbing(it)
    }
}

This function combines the code from inject, delareMock and the stubbing
usage:

val useCase: LeaguesUseCase by mock {
        whenever(getTeams()) doReturn Single.just(emptyList())
    }

I believe this would look much nicer.

2nd part:

As we use Kotlin Mockito, as shown above, I would rather have a version for that.
Would look similar:

inline fun <reified T: Any> KoinTest.mock(
    name: String = "",
    noinline parameters: ParameterDefinition = emptyParameterDefinition(),
    crossinline stubbing: KStubbing<T>.(T) -> Unit = {}
) = lazy {
    declareMock<T>()
    getKoin().get<T>(name, parameters).also {
        KStubbing(it).stubbing(it)
    }
}

usage:

val useCase: LeaguesUseCase by mock {
        on {getTeams()} doReturn Single.just(emptyList())
    }

I understand you don't want to add Kotlin Mockito as a dependency. Maybe you have an idea how to combine both? Or in addition of the first version have one similar to on{} of Kotlin mockito. Its not complex, just needs to return OngoingStubbing from Mockito

Target Koin project
koin-test

@arnaudgiuliani
Copy link
Member

Interesting proposal, thanks @dpreussler 👍

@arnaudgiuliani arnaudgiuliani added this to the 1.0.2 milestone Sep 30, 2018
@arnaudgiuliani
Copy link
Member

This feature is very interesting but a bit problematic because a lazy property won't be triggered at start. And if we want to predeclare mocks, we will have problems with overrides from the original and other stuff like that (because you predeclare a mock, and you load your original config).

A first approach is to extend the declareMock like that:

class CoffeeMakerTest : AutoCloseKoinTest() {

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

    @Before
    fun before() {
        startKoin(listOf(coffeeAppModule))
        declareMock<Heater> {
            given(isHot()).will { true }
        }
    }

    @After
    fun after() {
        stopKoin()
    }

    @Test
    fun testHeaterIsTurnedOnAndThenOff() {
        coffeeMaker.brew()

        verify(heater, times(1)).on()
        verify(heater, times(1)).off()
    }
}

@arnaudgiuliani arnaudgiuliani added the status:checking currently in analysis - discussion or need more detailed specs label Oct 26, 2018
@arnaudgiuliani
Copy link
Member

declareMock has to been after statrKoin & inject is triggered lazily once everything is already declared. This is 2 quite different moments that need Koin to be started.

We can't declare things in a lazy way, because nothing is triggered (like lazy of declareMock).

This code has to be triggered manually then:

    declareMock<T>()
    getKoin().get<T>(name, parameters).also {
        KStubbing(it).stubbing(it)
    }

I fixed the original declareMock to find and override the original definition.

Any idea else?

@dpreussler
Copy link
Author

understand but we still can pass the stubbing to declare mock right?

@arnaudgiuliani
Copy link
Member

@dpreussler yes

xmellado added a commit to xmellado/clean-architecture-koin-boilerplate that referenced this issue Jan 5, 2019
1) Mockito Android 2.23.x is not compatible with current stable Android Gradle Plugin. Android Gradle Plugin 3.3.0-beta02 or higher is needed. See: mockito/mockito#1511
2) Koin 1.0.2 makes browser activity tests fail. It is probably an issue with the updated declareMock function. See: InsertKoinIO/koin#243
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:checking currently in analysis - discussion or need more detailed specs test
Projects
None yet
Development

No branches or pull requests

2 participants