如何模拟Android Instrumented Test用例中的最终类,即模拟Android Run Time
中的最终级?
(我使用的是Mockito 2.X
)
我有一个测试用例如下-
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
// This is my app specific NON - Final class
private ShutdownServicesReqSig rebootSig = ShutdownServicesReqSig.newBuilder(ShutDownType.REBOOT_SYSTEM).setReason("test").build();
private PowerManager mockedPowerManager = null;
private Context mockedContext = null;
@Test
public void testRestart() throws InterruptedException
{
mockedContext = Mockito.mock(Context.class);
mockedPowerManager = Mockito.mock(PowerManager.class); // Here is the problem android.os.PowerManager is a Final class in latest Android SDK
// I need to mock it, only then I can use Mockito.verify() on PowerManager
Mockito.when(mockedContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mockedPowerManager);
assertTrue(executor.requestShutdown(rebootSig));
Thread.sleep(1000);
Mockito.verify(mockedPowerManager).reboot(any(String.class)); // Mocking of PowerManager is essential to be sure of method call on PowerManager, using Mockito.verify
Mockito.reset(mockedPowerManager);
}
}
当我在ART
上作为Android Instrumented Test运行它时(放在MyApplicationappsrcandroidTest
内部),我得到了以下错误-
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class android.os.PowerManager
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
但是,同样的代码,当我作为一个普通的JUnit测试运行时,在JVM
中(放在-MyApplicationappsrctest
中),它运行得非常好。
我需要在ART
中运行它,因为我喜欢测试一些定制的Android服务,并且我需要模拟像PowerManager
这样的最终类,因为只有这样我才能在PowerManager
上使用Mockito.verify()
来验证PowerManager
上的某些方法调用。
感谢您的帮助/指导。
Mockito 2有一个"选择加入"机制,可以模拟最终的方法或类,请参阅此处。您可以通过mockito扩展机制来启用它,方法是创建包含一行的文件src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
:
mock-maker-inline
(好吧,那个文件需要在类路径中)。
如果这对你有用,那就完美了。如果没有,你可能就无能为力了。
你看,检测可以归结为:操纵字节码。通常,使用多个框架来实现这一点是行不通的。
意思是:为了实现这种嘲讽,需要对字节码进行操作。出于显而易见的原因,让两个不同的字节码操作框架很好地共存是一个非常艰巨的挑战。
长话短说:试试这种扩展机制,当它不起作用时,你必须退一步问问自己:我打算实现的最终目标到底是什么?!
最有可能的是,你可能不应该浪费时间去嘲笑ART中运行的东西
为了模拟和监视最终类&在Android集成测试和Android Instrumentation测试中,您只需要将以下依赖项添加到您的build.gradle文件中:
androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito-inline-extended:2.28.1"
- 确保删除任何其他用作
androidTestImplementation
的mockito
依赖项 - 此外,如果您已经创建了一个
mockito-extensions/org.mockito.plugins.MockMaker
文件,请确保将其删除 - 这种依赖性适用于运行Android P或更高版本的设备
- 有关此依赖关系的更多详细信息,请参阅以下链接:Link1、Link2