mockito / mockito-kotlin

Using Mockito with Kotlin
MIT License
3.1k stars 200 forks source link

Possible to stub a field? #378

Open glureau-betclic opened 4 years ago

glureau-betclic commented 4 years ago

This may be a feature request and is related to #368

When spying + stubbing a field, the stub is actually on the getter but not on the field used internally in the class, as this snippet shows:

class B {
    var property: String? = null
        private set

    fun methodA(): String? = (::property).get() // OK
    fun methodB(): String? = property // KO
}

@Test
fun `spy and stub a property doesn't stub the internal field`() {
    val b = spy(B())
    whenever(b.property).doReturn("A string")
    b.methodA() `should be` "A string" // Passed
    b.methodB() `should be` "A string" // Failed: output is null
}

It's not very user-friendly, so could we improve in some ways for this? (Maybe a lint warning or something in the base documentation, if it's not technically feasible?)

AgiMaulana commented 4 years ago

fun methodA(): String? = (::property).get() delegates getProperty() when its called, which is the getProperty() already stubbed when the code runs whenever(b.property).doReturn("A string").

Meanwhile the fun methodB(): String? = property calls the property and the value is null

Tldr; whenever(b.property).doReturn("A string") stubs getProperty() method not the property

AgiMaulana commented 4 years ago

you can figure it by viewing Kotlin decompiled Java bytecode

glureau-betclic commented 4 years ago

I understood the behaviour, but I don't think it's user friendly.

What if whenever(b.property) mocks the property and the getter by default?