https://kotlinlang.org logo
Title
a

Anthony f

03/07/2019, 5:28 PM
hello guys, I try to mock/verify String.format(....)
I know this is a inline function
So I expect this is replace at compile time
so how handle it
o

oleksiyp

03/07/2019, 5:34 PM
No, no way to mockk inlines
How would you do that test so ?
with a intermediate object that map the inline function ?
I even try to mock the inside of the inline function, but I got some issue...
o

oleksiyp

03/07/2019, 7:18 PM
ehh... I don't know if I should write this at all. There is no normal way to do that. Was just curious how to hack it.
mockkConstructor(Formatter::class)

    every { anyConstructed<Formatter>().format("abc %s %d", "def", 123) } answers {
        mockk { every { this@mockk.toString() } returns "second" }
    }

    println("abc %s %d".format("def", 123))
But mocking other cases to return normal formatting is not easy:
mockkConstructor(Formatter::class)

    every { anyConstructed<Formatter>().format(any(), *anyVararg()) } answers {
        val res = callOriginal()

        val toS = res::class.memberProperties.first {
            it.name == "a"
        }!!.getter.apply { isAccessible = true }(res)?.toString() ?: "null"

        mockk { every { this@mockk.toString() } returns toS }
    }
    every { anyConstructed<Formatter>().format("abc %s %d", "def", 123) } answers {
        mockk { every { this@mockk.toString() } returns "second" }
    }

    println("abc  %s".format("def"))
    println("abc %s %d".format("ghi", 123))
    println("abc %s %d".format("def", 123))

`
l

LeoColman

03/07/2019, 10:11 PM
Just pass a string that wil be formatted
And verify that the end value is correct. You're mocking too much of the implementation, and that's usually a bad practice
1
t

thanksforallthefish

03/08/2019, 6:37 AM
Agree! I come from the day of jmock, I mock only interfaces (in general). Static methods don't define a contract, they are specific implementation I see no reason (well I do, but usually I see smell like missing providers or clean code practice) to mock them as the behavior is one and only one.
a

Anthony f

03/14/2019, 10:45 AM
Thanks for your comment, there are valuables. The point is that I’m on Android, so I need to resolve my string resources to run what you said. (I’m also trying to run roboelectric to get this working, but I have an open issue). So my idea was to spy the “format” function to then verify the sequence call of this “format” function with expected param. Would you do in an other way @oleksiyp @LeoColman @thanksforallthefish ?
o

oleksiyp

03/14/2019, 10:59 AM
Extract format to a class with interface
And mock it
Ah... probably it is because you need to deal with resources
Do you need this test at all? 😄 what's its value?
a

Anthony f

03/14/2019, 11:11 AM
It is contractual...
sometimes it is more easy/faster/safer to test everything, than ask is you should test or not !
would it be complexe to be able to spyk it ? as well as spy static and object (that are not available in mockk today)
o

oleksiyp

03/14/2019, 11:16 AM
mockkStatic and mockkObject are rather spy than mock
a

Anthony f

03/14/2019, 11:22 AM
... but when you use mockkStatic and mockkObject you have to define every stub, isn’t it ? so from my understanding I would not call it a spy. Am I wrong ?
o

oleksiyp

03/14/2019, 11:23 AM
You don't need to define
a

Anthony f

03/14/2019, 11:27 AM
if I mock Application.Companion.applicationContext, then I have to setup the return value like :
mockkObject(EDFApplication.Companion)

every { Application.applicationContext().getString(any()) } returns ""
every { Application.applicationContext().getString(any(), any(), any()) } returns ""