tmurakami / dexopener

An Android library that provides the ability to mock your final classes on Android devices.
Apache License 2.0
113 stars 4 forks source link

Not able to mock static class of third party library #27

Closed mistrydarshan99 closed 3 years ago

mistrydarshan99 commented 3 years ago

I have tried to mock third party library static class in UI testing that worked very well in android above API 29 without using DexOpener.

For mock static class I have used Mockk Library . In Mockk they suggested to used dexopener library to mock final class before API 29.

When I configure this library and try to run test it fails and log the error not able to mock static class.

tmurakami commented 3 years ago

See the mockk example. https://github.com/tmurakami/dexopener/tree/master/examples/mockk https://github.com/tmurakami/dexopener/blob/master/examples/mockk/src/androidTest/java/com/example/dexopener/mockk/MyServiceTest.kt

mistrydarshan99 commented 3 years ago

Thanks for pointing out example of mockk. In your example I have add one file with top level function file like below.

@file:JvmName("Test")
package com.example.dexopener.mockk

fun isLogin(): Boolean {
    return false;
}

In MainActivityTest.kt file I have write test case like this.

    @Test
    fun test_top_level_function_is_able_to_mock(){
        mockkStatic("com.example.dexopener.mockk.Test")
        every { isLogin() } returns true
        assertTrue(isLogin())
    }

The same function works very well above api 29. But below API 29 I am not able to mock function and it gives me below exception.

io.mockk.MockKException: Failed to build static proxy at io.mockk.impl.instantiation.JvmStaticMockFactory.staticMockk(JvmStaticMockFactory.kt:41) at com.example.dexopener.mockk.MainActivityTest.test_top_level_function(MainActivityTest.kt:111) at java.lang.reflect.Method.invoke(Native Method) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80) at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:154) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:27) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at org.junit.runner.JUnitCore.run(JUnitCore.java:115) at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56) at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:395) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2169) Caused by: io.mockk.proxy.MockKAgentException: Mocking static is supported starting from Android P at io.mockk.proxy.android.StaticProxyMaker.staticProxy(StaticProxyMaker.kt:35) at io.mockk.impl.instantiation.JvmStaticMockFactory.staticMockk(JvmStaticMockFactory.kt:39) ... 31 more

Tests ran to completion.

tmurakami commented 3 years ago

You need to skip the test with @SdkSuppress. https://github.com/tmurakami/dexopener/blob/e590ff3629352123924fcc66ed72036ad385b2ad/examples/mockk/src/androidTest/java/com/example/dexopener/mockk/MyServiceTest.kt#L30

See "Supported features" in the "MockK Android support" page. https://mockk.io/ANDROID.html DexOpener supports only "mocking final classes" and not "extension function mocking (static mocks)".

mistrydarshan99 commented 3 years ago

Is there any other third party library using which we able to test "extension function mocking (static mocks)" before API 29.

I don't want to skip test before API 29 that's why I am asking any other way to achieve "extension function mocking (static mocks)".

tmurakami commented 3 years ago

I'm sorry, I don't know.