Java – Android: Mockito (2. 0.2-beta) – Cannot simulate/monitor final class

Android: Mockito (2. 0.2-beta) – Cannot simulate/monitor final class… here is a solution to the problem.

Android: Mockito (2. 0.2-beta) – Cannot simulate/monitor final class

I used mockito-all, version: '2.0.2-beta' to simulate PowerManager in my Android Instrumental test, which was the last lesson

I get –

org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class android.os.PowerManager
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
at com.crsardar.handson.android.mockito.ExampleInstrumentedTest.useAppContext(ExampleInstrumentedTest.java:38)
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 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 android.support.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:101)
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 android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:384)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1932)

My app's build.gradle is as follows –

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.crsardar.handson.android.mockito"
        minSdkVersion 25
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

configurations.all {
        resolutionStrategy {
            force 'com.android.support:support-annotations:26.1.0'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation group: 'org.mockito', name: 'mockito-all', version: '2.0.2-beta'
}

My tool test case is as follows −

package com.crsardar.handson.android.mockito;

import android.content.Context;
import android.os.PowerManager;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {

private Context mockedContext = null;

@Test
    public void useAppContext() {

PowerManager mockedPowerManager = mock(PowerManager.class);
        System.out.println("Before mockedPowerManager = " + mockedPowerManager.hashCode());

mockedContext = mock(Context.class);

when(mockedContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mockedPowerManager);

System.out.println("After mockedPowerManager = " + mockedContext.getSystemService(Context.POWER_SERVICE).hashCode());
    }
}

None of the existing posts in StackOverflow helped, any help is greatly appreciated

Solution

ShadowPowerManager can be used in the following ways:

  private PowerManager powerManager;
  private ShadowPowerManager shadowPowerManager;

@Before
  public void before() {
    powerManager =  (PowerManager)ApplicationProvider.getApplicationContext().getSystemService(Context.POWER_SERVICE);
    shadowPowerManager = shadowOf(powerManager);
    shadowPowerManager.setIsScreenOn(false);
  }

Related Problems and Solutions