mockito-kotlin icon indicating copy to clipboard operation
mockito-kotlin copied to clipboard

Possible to stub a field?

Open glureau-betclic opened this issue 4 years ago • 3 comments

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?)

glureau-betclic avatar Mar 23 '20 10:03 glureau-betclic

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 avatar Jun 25 '20 07:06 AgiMaulana

you can figure it by viewing Kotlin decompiled Java bytecode

AgiMaulana avatar Jun 25 '20 07:06 AgiMaulana

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?

glureau-betclic avatar Jul 06 '20 20:07 glureau-betclic