2

I would like to mock a property setter in my test, but I can't find anything on how one does it. Here is what I have tried so far:

interface Foo
{
    var property: Int
}

@RunWith(MockitoJUnitRunner::class)
class TestClass
{
    @Mock private val fooMock: Foo = mock()
    private var temp = 0

    @Before
    fun setup()
    {
        whenever(fooMock.property).then {
            invocation ->
            if (invocation.arguments.isEmpty())
            {
                // this part works fine
                return@then 15
            }
            else
            {
                // this never gets called
                temp = invocation.getArgument(0)
                null
            }
        }
    }
}

note: I am using com.nhaarman.mockito_kotlin library

rozina
  • 4,120
  • 27
  • 49
  • Another option to solving this problem is to configure Mockito to handing the mocking of property setters: https://stackoverflow.com/a/48834284/1486374 – levibostian Feb 28 '19 at 15:19

1 Answers1

6

A slightly ugly, but working solution for mocking a setter, using a bound property reference to get the setter:

whenever(fooMock::property.setter.invoke(any())).then {
    println("setter called with ${it.arguments[0]}")
}

Some alternatives:

If you want to verify that a property was set to a given value, you can do the following:

fooMock.property = 25

verify(fooMock).property = 25

If you want to capture the value that the property was set to, you can use an ArgumentCaptor, like so:

class TestClass {
    @Mock private lateinit var fooMock: Foo
    @Captor private lateinit var captor: ArgumentCaptor<Int>

    @Test
    fun test() {
        fooMock.property = 25

        verify(fooMock).property = capture(captor)

        assertEquals(25, captor.value)
    }
}

General hint for Mockito: these two lines both create a mock, you don't need to use both the @Mock annotation and the mock() method.

@Mock private lateinit var fooMock: Foo

private val fooMock: Foo = mock()
zsmb13
  • 85,752
  • 11
  • 221
  • 226
  • Awsome thank you! I know about verifying and capturing, and in my case this isn't enough. The property is being accessed twice and set once in between the same call of the function, and I need to emulate this. Also didn't know I can skip the annonation :) – rozina May 25 '17 at 11:04
  • In case you're not interested in using Kotlin reflection, you can use a Mockito configuration to solve this problem: https://stackoverflow.com/a/48834284/1486374 – levibostian Feb 28 '19 at 15:17