2

Is there any way I can Mock Static Function in Android using any Mocking Framework. Mockito can mock classes but is insuffiecient to mock Static functions.

Any help will be highly appreciated.

Thanks in Advance

Rohit Jindal
  • 679
  • 1
  • 10
  • 21

3 Answers3

2

Mocking works by using the concepts of Object Orientation, Inheritance etc....

Basically by overriding certain methods & behaviour in objects / instances that look like real objects, because they are subclasses of these real objects.

In other words, the mocking part comes in overriding methods on instances.

It is not possible to override a static method (afaik).

Therefore mocking of static calls is not easy (if even possible).


EDIT - I was wrong...

As it turns out, I was wrong in my above statement that it is not possible.

I should have searched this site for duplicate questions. See below for some links to frameworks that claim to do this for you in some cases. Since they work with bytecode, I'm not sure they will work properly on Android (ymmv).


(thanks to Rohit for forcing me to reassess my beliefs)

Community
  • 1
  • 1
Richard Le Mesurier
  • 29,432
  • 22
  • 140
  • 255
  • 2
    But I am able to Mock Static functions in Java Project using PowerMockito and Mockito. But I am not able to do so in Android Project. – Rohit Jindal Feb 05 '13 at 09:12
  • I add dexmaker, mockito, it can work well in Android. But PowerMockito libs seem not work well. – brucenan Apr 28 '14 at 08:08
0

Please try this instead: https://bintray.com/linkedin/maven/dexmaker-mockito-inline-extended

It helps me successfully mock the static method in the Android Instrumented Tests, but note that this feature requires running on a device with at least Android P.

Here is what I did:

  • Replace the androidTestImplementation 'org.mockito:mockito-android:2.28.0' with androidTestImplementation 'com.linkedin.dexmaker:dexmaker-mockito-inline-extended:2.28.0'

  • Then mock the static method like this:

    static class StaticTrojan {
        static String staticOpen() { return "horse"; }
    }
    
    @Test
    public void testStubbingStaticMethod() {
        MockitoSession session = mockitoSession().spyStatic(StaticTrojan.class).startMocking();
        try {
            when(StaticTrojan.staticOpen()).thenReturn("soldiers");
            assertEquals("soldiers", StaticTrojan.staticOpen());
        } finally {
            session.finishMocking();
        }
    
        // Once the session is finished, all stubbings are reset
        assertEquals("horse", StaticTrojan.staticOpen());
    }
    
0

If you use Kotlin, then to mocking static functions you can connect the mockk library project:

androidTestImplementation "io.mockk:mockk-android:1.12.0"

Then you need to add a AndroidManifest.xml to the androidTest directory if your tests are located in the application module.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="you.application.package">

    <application
        android:debuggable="true"
        android:extractNativeLibs="true" />
</manifest>

Then you can mocking static functions using the following code:

import io.mockk.every
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import org.junit.Assert.assertEquals
import org.junit.Test

class TestMockingStaticFunction {

    object StaticTrojan {

        @JvmStatic
        fun staticOpen(): String {
            return "horse"
        }
    }

    @Test
    fun testMockingStaticFunction() {
        assertEquals("horse", StaticTrojan.staticOpen())

        mockkStatic(StaticTrojan::staticOpen)
        val mockScope = every { StaticTrojan.staticOpen() } returns "solders"

        assertEquals("solders", StaticTrojan.staticOpen())

        unmockkStatic(StaticTrojan::staticOpen)

        assertEquals("horse", StaticTrojan.staticOpen())
    }
}

Library API allows you to comfortably mock the Kotlin objects, in the example above the object is used only to create a static function using @JvmStatic annotation.

Attention! This approach uses JVMTI available in Android P starting from the API level 28. Your application can be written using a smaller API, but the tests you must run only on Android P devices or newer.

maXp
  • 1,428
  • 1
  • 15
  • 23