Mocking extension function in Kotlin

后端 未结 4 1437
暗喜
暗喜 2021-02-19 01:19

How to mock Kotlin extension function using Mockito or PowerMock in tests? Since they are resolved statically should they be tested as static method calls or as non static?

相关标签:
4条回答
  • 2021-02-19 01:30

    I use mockk library.

    For extension file write java name, like this:

    @file:JvmName(name = "ExtensionUtils")
    
    package myproject.extension
    
    ...
    

    And for fast codding I created file with different extension mocks:

    object FastMock {
    
        fun extension() = mockkStatic("myproject.extension.ExtensionUtils")
    
        fun listExtension() = mockkStatic("myproject.extension.ListExtensionUtils")
    
    }
    

    In test call this:

    FastMock.listExtension()
    every { itemList.move(from, to) } returns Unit
    
    0 讨论(0)
  • 2021-02-19 01:35

    I think MockK can help you.

    It supports mocking extension functions too.

    You can use it to mock object-wide extensions:

    data class Obj(val value: Int)
    
    class Ext {
        fun Obj.extensionFunc() = value + 5
    }
    
    with(mockk<Ext>()) {
        every {
            Obj(5).extensionFunc()
        } returns 11
    
        assertEquals(11, Obj(5).extensionFunc())
    
        verify {
            Obj(5).extensionFunc()
        }
    }
    

    If you extension is a module-wide, meaning that it is declared in a file (not inside class), you should mock it in this way:

    data class Obj(val value: Int)
    
    // declared in File.kt ("pkg" package)
    fun Obj.extensionFunc() = value + 5
    
    mockkStatic("pkg.FileKt")
    
    every {
        Obj(5).extensionFunc()
    } returns 11
    
    assertEquals(11, Obj(5).extensionFunc())
    
    verify {
        Obj(5).extensionFunc()
    }
    

    By adding mockkStatic("pkg.FileKt") line with the name of a package and file where extension is declared (pkg.File.kt in the example).

    More info can be found here: web site and github

    0 讨论(0)
  • 2021-02-19 01:38

    Instance extension functions can be stubbed and verified like this with the help of mockito-kotlin:

    data class Bar(thing: Int)
    
    class Foo {
       fun Bar.bla(anotherThing: Int): Int { ... }
    }
    
    val bar = Bar(thing = 1)
    val foo = mock<Foo>()
    
    with(foo) {
      whenever(any<Bar>().bla(any()).doReturn(3)
    }
    
    verify(foo).apply {
      bar.bla(anotherThing = 2)
    }
    
    0 讨论(0)
  • 2021-02-19 01:50

    First of all, Mockito knows nothing Kotlin specific language constructs. In the end, Mockito will have a look into the byte code. Mockito is only able to understand what it finds there and what looks like a Java language construct.

    Meaning: to be really sure, you might want to use javap to deassemble the compiled classfiles to identify the exact names/signatures of the methods you want to mock.

    And obviously: when that method is static, you have to user PowerMock, or JMockit; if not, you should prefer to with Mockito.

    From a java point of view, you simply avoid mocking static stuff; but of course, things get really interesting, now that different languages with different ideas/concepts come together.

    0 讨论(0)
提交回复
热议问题