简体   繁体   English

Android测试,模拟最终课程

[英]Android Instrumented Test, Mock Final Classes

How to mock final classes inside Android Instrumented Test cases, that is mocking final classes inside Android Run Time ? 如何在Android Instrumented测试用例中模拟最终类,即在Android Run Time模拟最终类?

(I am using Mockito 2.X ) (我正在使用Mockito 2.X

I have a test case like follows - 我有一个如下的测试用例-

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);
    }
}

When I am running it as Android Instrumented Test on ART (placing inside - MyApplication\\app\\src\\androidTest ), I am getting following error - 当我将其作为ART上的Android Instrumented Test(放置在MyApplication\\app\\src\\androidTest )运行时,出现以下错误-

org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class android.os.PowerManager
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types

But, the same code, when I am running as a normal JUnit test, inside JVM (placing inside - MyApplication\\app\\src\\test ) it is working perfectly fine. 但是,同样的代码,当我作为普通的JUnit测试运行时,在JVM内部(放置在MyApplication\\app\\src\\test ),可以正常工作。

I need to run it inside ART , as I like to test some of my customized Android Services, and I need to mock final classes like PowerManager , as only then I can use Mockito.verify() on PowerManager , to verify certain method calls on PowerManager . 我需要在ART运行它,因为我想测试一些自定义的Android服务,并且需要模拟诸如PowerManager最终类,因为只有这样我才能在PowerManager上使用Mockito.verify()来验证对某些方法的调用PowerManager

Help/guides are appreciated. 帮助/指南表示赞赏。

Mockito 2 has an "opt-in" mechanism to enable mocking of final methods or classes, see here . Mockito 2具有“选择加入”机制,可以模拟最终方法或类,请参见此处 You enable it via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line: 通过创建包含一行的文件src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker ,可以通过模仿扩展机制启用它:

mock-maker-inline

(well, that file needs to be in the class path). (好吧,该文件必须位于类路径中)。

If that works for you, perfect. 如果这对您有用,那就完美。 If not, there is probably nothing else you can do. 如果没有,您可能无能为力。

You see, instrumenting boils down to: manipulating byte code. 您会发现,检测归结为:处理字节码。 Typically, it doesn't work out to use more than one framework doing that. 通常,使用一个以上的框架来完成工作是不可行的。

Meaning: in order to enable that kind of mocking, bytecode needs to be manipulated. 含义:为了实现这种模拟,需要对字节码进行操作。 And for obvious reasons, getting two different bytecode manipulation frameworks to nicely coexist is a very tough challenge. 出于显而易见的原因,要使两个不同的字节码操作框架很好地共存是一个非常艰巨的挑战。

Long story short: try that extension mechanism, when it doesn't work you have to step back and ask yourself: what exactly is the final goal I intend to achieve?! 长话短说:尝试这种扩展机制,当它不起作用时,您必须退后一步并问自己:我打算实现的最终目标到底是什么?

Most likely, you probably shouldn't waste your time trying to mock things running within ART. 最有可能的是,您可能不应该浪费时间尝试模拟在ART中运行的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM