https://kotlinlang.org logo
#announcements
Title
# announcements
a

Andreas Unterweger

09/22/2019, 8:07 PM
hi everybody, im using mockk for mocking the following test fails on the second assertion (returned value is 1 instead of 2). why?
Copy code
class Test {

    @test
    internal fun name() {
        val mock = mockk<Logic>()
        every { mock.doSth() } returns 2
        mock.doSth() shouldBe 2

        val obj = object : HasLogic {}
        obj.doSth() shouldBe 2
    }
}

interface HasLogic {
    fun doSth() = Logic.doSth()
}

object Logic {
    fun doSth() = 1
}
w

wasyl

09/22/2019, 8:10 PM
You need to use triple backticks to format multiline code 🙂 ` ``` `
a

Andreas Unterweger

09/22/2019, 8:10 PM
thx just fixed it
w

wasyl

09/22/2019, 8:11 PM
Anyway it doesn’t work, because when you’re mocking
Logic
by doing
val mock = mockk<Logic>()
it’s only
mock
variable which, well, is a mock.
mockk<Logic>()
does not change the
object Logic
that you define
a

Andreas Unterweger

09/22/2019, 8:11 PM
how can i mock all instances?
w

wasyl

09/22/2019, 8:12 PM
and since
HasLogic
interface uses
Logic
object directly, and not your mock, it uses real implementation
a

Andreas Unterweger

09/22/2019, 8:12 PM
im coming from jmockit and there this would work
w

wasyl

09/22/2019, 8:14 PM
im coming from jmockit and there this would work
The difference is
Logic.doSth
is not a static method call — it’s a method declared on a
Logic
singleton instance. If you really need and want static methods, you should drop
object Logic
declaration whatsoever. Top-level functions are static jvm methods
Maybe adding
@JvmStatic
would works as well, but I wouldn’t know. Either way you wouldn’t me mocking the entire
Logic
object, rather each function separately, I guess? Not really sure how to help here, since generally what you should do for testability is to inject the dependencies into the objects you’re testing
a

Andreas Unterweger

09/22/2019, 8:48 PM
hmmm...i just tried @jvmstatic that gives a compilation error. i will further investigate but i assume there must be a solution, otherwise it would be a big drawback...anyways thank you
found the answer
Copy code
class Test {

    @Test
    internal fun name() {
        mockkObject(Logic)
        every { Logic.doSth() } returns 2

        val obj = object : HasLogic {}
        obj.doSth() shouldBe 2
    }
}

interface HasLogic {
    fun doSth() = Logic.doSth()
}

object Logic {

    fun doSth() = 1
}
w

wasyl

09/22/2019, 9:15 PM
Interesting. What would happen if you didn’t write
val mock = mockkObject(Logic)
?
Anyway that makes sense if
mockk
library works like that. I’m not using so I wasn’t very helpful 😐
a

Andreas Unterweger

09/22/2019, 10:52 PM
works without the val assignment too will fix it
j

James Richardson

09/23/2019, 6:58 AM
So that's sorted out the how, but the why remains. You've just tested your mock implementation. Seems odd...
Usually mocks are handy for collaborators of a thing that's being tested not the implementation of it.
a

Andreas Unterweger

09/23/2019, 10:19 AM
well, i guess its a corner case. if
Logic.doSth()
is an expensive operation, which is tested in its own unit test, i think it can make sense to only verify its called to save runtime
4 Views