1

I'd want to use doReturn(sth).when(underTest).someFunc() instead of when(underTest.someFunc()).thenReturn(sth).
(don't want to actually execute anything inside someFunc() - https://stackoverflow.com/a/29394497/541624)

In Java, I could do underTest = Mockito.spy(new SomeClass(someParam));

I'm getting:

Mockito cannot mock/spy because :
 - final class
ericn
  • 12,476
  • 16
  • 84
  • 127
  • 1
    There's nothing wrong with `underTest = Mockito.spy(SomeClass(someParam))` in kotlin. Also, check out https://github.com/nhaarman/mockito-kotlin if you want nicer syntax for mockito in kotlin. – Can_of_awe Apr 16 '19 at 14:05

1 Answers1

0

The reason you cannot mock/spy Kotlin classes is they are final (by default). So Mockito cannot mock such classes unless you put the keyword open.

The Mockito version 2 introduced a feature which allows you to mock/spy final classes.

How to do it? Add mockito-inline dependency with other mockito v2 dependencies. For ex: testImplementation 'org.mockito:mockito-inline:2.8.9'

Then use mockito methods as normal.

Here's a dummy test which demonstrates how to mock a method and do nothing.

class Foo {
    var xval = 0
    fun foo(x: Int, y: Int): Int = x / y

    fun bar(x: Int) {
        xval = x
    }
}

class FooTest {
    @Test
    fun fooTest() {
        val foo = Mockito.mock(Foo::class.java)
        Mockito.doAnswer(Answers.RETURNS_DEFAULTS).`when`(foo).foo(10, 2)

        assertEquals(0, foo.foo(10, 2))

        Mockito.doNothing().`when`(foo).bar(100)

        assertEquals(0, foo.xval)
    }
}

As you can see, you could return defaults for methods which return something or do nothing for void methods.

Otherwise, you could use mockk https://mockk.io/ library which doesn't have this issue.

Having said all the above, I suggest that think if you could use an interface/abstract class rather than a concrete class here. That’s the best way to abstract away your dependency using mocking.

Laksitha Ranasingha
  • 4,321
  • 1
  • 28
  • 33