mockingmockitokotlinpowermockpowermockito

How to mock a Kotlin singleton object?


Given a Kotlin singleton object and a fun that call it's method

object SomeObject {
   fun someFun() {}
}

fun callerFun() {
   SomeObject.someFun()
}

Is there a way to mock call to SomeObject.someFun()?


Solution

  • Just make your object implement an interface, then you can mock your object with any mocking library. Here is an example using Junit + Mockito + Mockito-Kotlin:

    import com.nhaarman.mockito_kotlin.mock
    import com.nhaarman.mockito_kotlin.whenever
    import org.junit.Assert.assertEquals
    import org.junit.Test
    
    object SomeObject : SomeInterface {
        override fun someFun():String {
            return ""
        }
    }
    
    interface SomeInterface {
        fun someFun():String
    }
    
    class SampleTest {
    
        @Test
        fun test_with_mock() {
            val mock = mock<SomeInterface>()
    
            whenever(mock.someFun()).thenReturn("42")
    
            val answer = mock.someFun()
    
            assertEquals("42", answer)
        }
    }
    

    Or in case you want to mock SomeObject inside callerFun:

    import com.nhaarman.mockito_kotlin.mock
    import com.nhaarman.mockito_kotlin.whenever
    import org.junit.Assert.assertEquals
    import org.junit.Test
    
    object SomeObject : SomeInterface {
        override fun someFun():String {
            return ""
        }
    }
    
    class Caller(val someInterface: SomeInterface) {
        fun callerFun():String {
            return "Test ${someInterface.someFun()}"
        }
    }
    
    // Example of use
    val test = Caller(SomeObject).callerFun()
    
    interface SomeInterface {
        fun someFun():String
    }
    
    class SampleTest {
    
        @Test
        fun test_with_mock() {
            val mock = mock<SomeInterface>()
            val caller = Caller(mock)
    
            whenever(mock.someFun()).thenReturn("42")
    
            val answer = caller.callerFun()
    
            assertEquals("Test 42", answer)
        }
    }