0

When I built a structure like the one below, I saw that the classes that are not executed through the interfacecan also be mockable. How does this work? Could it be related to Kotlin?

In fact, my question here is; How does it crush the function of a class without override? I'm curious about the background of this.

class Sample {
    fun returnFive() = 5
}

@Test
fun test(){
    var sample = Sample()
    sample = mockk {
        every { returnFive() } returns 10
    }
    assertEquals(5,sample.returnFive())
}
LeoColman
  • 6,950
  • 7
  • 34
  • 63
Hasan Kucuk
  • 2,433
  • 6
  • 19
  • 41

1 Answers1

1

Your code can be rewritten as

class Sample {
    fun returnFive() = 5
}

@Test
fun test() {
    val sample: Sample = mockk()

    every { sample.returnFive() } returns 10

    assertEquals(10, sample.returnFive()) 
}

This allows us to see that sample becomes an instance of Sample, but Mockk is creating it, not you.

When you delegate this creation to Mockk, it does some magic to replace that instance with an instrumented one, which you can define extra behaviours. Mockk's author explained a little bit more about this in this blog post if you're interested.


Could it be related to Kotlin?

This isn't exactly Kotlin's behaviour.

You could do the same thing when using Java with Mockito, for example.

LeoColman
  • 6,950
  • 7
  • 34
  • 63
  • In fact, my question here is; How does it crush the function of a class without "override"? I'm curious about the background of this. – Hasan Kucuk May 23 '20 at 08:46
  • 1
    It uses bytecode manipulation. I believe everything is done through ByteBuddy, but at a very high level: 1 - "subclass" your class. 2-make all the methods from your class delegate to mockk's class 3-let the program execute them as if it was your class – LeoColman May 23 '20 at 08:47