How to mock objects in Kotlin?

I want to test a class that calls an object (static method call in java) but I'm not able to mock this object to avoid real method to be executed.

object Foo {
    fun bar() {
        //Calls third party sdk here

I've tried different options like Mockk, How to mock a Kotlin singleton object? and using PowerMock in the same way as in java but with no success.

Code using PowerMockito:

class EditProfilePresenterTest {

    fun shouldCallIntentGenerator() {

        val intent = mock(

        PowerMockito.`when`(IntentGenerator.newIntent(any())).thenReturn(intent) //newIntent method param is context




With this code I get

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method com.sample.test.IntentGenerator$Companion.newIntent, parameter context

any() method is from mockito_kotlin. Then If I pass a mocked context to newIntent method, it seems real method is called.


  • First, that object IntentGenerator looks like a code smell, why would you make it an object? If it's not your code you could easily create a wrapper class

    class IntentGeneratorWrapper {
        fun newIntent(context: Context) = IntentGenerator.newIntent(context)    

    And use that one in your code, without static dependencies.

    That being said, I have 2 solutions. Say you have an object

    object IntentGenerator {
        fun newIntent(context: Context) = Intent()

    Solution 1 - Mockk

    With Mockk library the syntax is a bit funny compared to Mockito but, hey, it works:

    testCompile "io.mockk:mockk:1.7.10"
    testCompile "com.nhaarman:mockito-kotlin:1.5.0"

    Then in your test you use objectMockk fun with your object as argument and that will return a scope on which you call use, within use body you can mock the object:

    fun testWithMockk() {
        val intent: Intent = mock()
        objectMockk(IntentGenerator).use {
            every { IntentGenerator.newIntent(any()) } returns intent
            Assert.assertEquals("meow", IntentGenerator.newIntent(mock()).action)

    Solution 2 - Mockito + reflection

    In your test resources folder create a mockito-extensions folder (e.g. if you're module is "app" -> app/src/test/resources/mockito-extensions) and in it a file named org.mockito.plugins.MockMaker. In the file just write this one line mock-maker-inline. Now you can mock final classes and methods (both IntentGenerator class and newIntent method are final).

    Then you need to

    1. Create an instance of IntentGenerator. Mind that IntentGenerator is just a regular java class, I invite you to check it with Kotlin bytecode window in Android Studio
    2. Create a spy object with Mockito on that instance and mock the method
    3. Remove the final modifier from INSTANCE field. When you declare an object in Kotlin what is happening is that a class (IntentGenerator in this case) is created with a private constructor and a static INSTANCE method. That is, a singleton.
    4. Replace IntentGenerator.INSTANCE value with your own mocked instance.

    The full method would look like this:

    fun testWithReflection() {
        val intent: Intent = mock()
        // instantiate IntentGenerator
        val constructor =[0]
        constructor.isAccessible = true
        val intentGeneratorInstance = constructor.newInstance() as IntentGenerator
        // mock the the method
        val mockedInstance = spy(intentGeneratorInstance)
        doAnswer { intent }.`when`(mockedInstance).newIntent(any())
        // remove the final modifier from INSTANCE field
        val instanceField ="INSTANCE")
        val modifiersField ="modifiers")
        modifiersField.isAccessible = true
        modifiersField.setInt(instanceField, instanceField.modifiers and Modifier.FINAL.inv())
        // set your own mocked IntentGenerator instance to the static INSTANCE field
        instanceField.isAccessible = true
        instanceField.set(null, mockedInstance)
        // and BAM, now IntentGenerator.newIntent() is mocked
        Assert.assertEquals("meow", IntentGenerator.newIntent(mock()).action)

    The problem is that after you mocked the object, the mocked instance will stay there and other tests might be affected. A made a sample on how to confine the mocking into a scope here

    Why PowerMock is not working

    You're getting

    Parameter specified as non-null is null

    because IntentGenerator is not being mocked, therefore the method newIntent that is being called is the actual one and in Kotlin a method with non-null arguments will invoke kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull at the beginning of your method. You can check it with the bytecode viewer in Android Studio. If you changed your code to

    PowerMockito.doAnswer { intent }.`when`(IntentGenerator).newIntent(any())

    You would get another error

    org.mockito.exceptions.misusing.NotAMockException: Argument passed to when() is not a mock!

    If the object was mocked, the newInstance method called would not be the one from the actual class and therefore a null could be passed as argument even if in the signature it is non-nullable