Hot questions for Using Mockito in android studio

Top 10 Java Open Source / Mockito / android studio

Question:

I try to use Mockito from within Android Studio 1.2.2 but I get the following error:

Error:(50, 17) Failed to resolve: org.mockito:mockito-core:1.10.19

The error occurs when I sync Gradle after adding the dependency manually. This is the dependency in my module Gradle file:

    dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:22.2.0'
    testCompile 'org.mockito:mockito-core:1.10.19' 
}

Could anyone help my resolve this issue?

Related questions:

  1. Do I first need to download Mockito manually?
  2. If so, where should I put it?

Note: the comments were helpfull to solve the above problem. However, it got me into another problem which I could not solve. But updating to Android Studio 1.3 solved it. I am now running Mockito from within Android Studio.


Answer:

Try replacing testCompile with androidTestCompile, it works for me when importing Mockito libs.

However, you may run to a runtime error if you include only mockito-core. You'll need to add into your gradle:

androidTestCompile "org.mockito:mockito-core:1.10.19"
androidTestCompile "com.google.dexmaker:dexmaker:1.2"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"

If you have error with dexcache, put this line into your setUp() (Assuming you are using InstrumentalTestCase)

System.setProperty("dexmaker.dexcache", getInstrumentation().getTargetContext().getCacheDir().getPath());

Question:

Here's the relevant bit from my build.gradle:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'

    androidTestCompile "org.mockito:mockito-core:1.10.19"
    androidTestCompile 'com.google.dexmaker:dexmaker:1.0'
    androidTestCompile('com.google.dexmaker:dexmaker-mockito:1.0') {
        exclude module: 'hamcrest-core'
        exclude module: 'objenesis'
        exclude module: 'mockito-core'
    }
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
}

When I use @Mock annotation to declare a mock, it's null. But when I use

context = mock(Context.class);

then I get a properly mocked object. I'm using this in a Junit-3 TestCase, if that matters.

Why does the annotation not work?


Answer:

If you use JUnit 3, you have to use MockitoAnnotations in the set up method in your test :

public class ATest extends TestCase {
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    // ...
}

Annotations don't work out of the box, you have to instruct JUnit to do something. For a complete reference, with JUnit 4 you have other recommended options :

With a JUnit runner :

@RunWith(MockitoJUnitRunner.class)
public class ATest {
    @Mock Whatever w;

    // ...
}

Or with a JUnit rule :

public class ATest {
    @Rule MockitoRule mockitoRule = MockitoJUnit.rule();
    @Mock Whatever w;

    // ...
}

Question:

I am not able to mock object inside my unit test.

Code Snippet:

@Before
public void setUp(){
    MockitoAnnotations.initMocks(this);
}

@Test
public void test_employee_name() {
    Employee employee = Mockito.mock(Employee.class);
    when(employee.getName())
            .thenReturn("jitesh");
    assertEquals("jitesh", employee.getName());
}

Dependencies:

testImplementation 'org.mockito:mockito-core:2.7.22'

Gradle:

android {
    compileSdkVersion 28
    dataBinding {
        enabled = true
    }
    testOptions {
        unitTests.returnDefaultValues = true
    }
    defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.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'

    // Room components
    implementation "android.arch.persistence.room:runtime:1.1.1"
    annotationProcessor "android.arch.persistence.room:compiler:1.1.1"
    androidTestImplementation "android.arch.persistence.room:testing:1.1.1"
    annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
    implementation "android.arch.lifecycle:extensions:1.1.1"

    implementation 'com.android.support:design:28.0.0'
    testImplementation 'org.mockito:mockito-core:2.7.22' 
}

Error:

java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker
    at org.mockito.internal.configuration.plugins.PluginLoader$1.invoke(PluginLoader.java:66)
    at com.sun.proxy.$Proxy7.isTypeMockable(Unknown Source)
    at org.mockito.internal.util.MockUtil.typeMockabilityOf(MockUtil.java:29)
    at org.mockito.internal.util.MockCreationValidator.validateType(MockCreationValidator.java:22)
    at org.mockito.internal.creation.MockSettingsImpl.validatedSettings(MockSettingsImpl.java:186)
    at org.mockito.internal.creation.MockSettingsImpl.confirm(MockSettingsImpl.java:180)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:62)
    at org.mockito.Mockito.mock(Mockito.java:1729)
    at org.mockito.Mockito.mock(Mockito.java:1642)
    at com.example.myapplication.ExampleUnitTest.setUp(ExampleUnitTest.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    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.RunBefores.evaluate(RunBefores.java:24)
    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 org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.NoClassDefFoundError: net/bytebuddy/dynamic/loading/ClassLoadingStrategy
    at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.<init>(SubclassByteBuddyMockMaker.java:33)
    at org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker.<init>(ByteBuddyMockMaker.java:21)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:54)
    at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:18)
    at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:17)
    at org.mockito.internal.configuration.GlobalConfiguration.tryGetPluginAnnotationEngine(GlobalConfiguration.java:55)
    at org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:68)
    at com.example.myapplication.ExampleUnitTest.setUp(ExampleUnitTest.java:29)
    ... 22 more
Caused by: java.lang.ClassNotFoundException: net.bytebuddy.dynamic.loading.ClassLoadingStrategy
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

Answer:

Works for me in a simple Java project, so it might be a problem in your environment. Here is my minimal working example:

Productive class:

public class Employee {

    private String name;

    public String getName() {
        return name;
    }
}

Test class:

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

public class FooTest {
    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test_employee_name() {
        Employee employee = Mockito.mock(Employee.class);
        when(employee.getName())
                .thenReturn("jitesh");
        assertEquals("jitesh", employee.getName());
    }
}

Dependencies in pom:

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>2.7.22</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Question:

recently I've been struggling with Mockito. But after valiant efforts, I made it compile without errors except this one in a particular case :

When I'm mocking a package-private class with Mockito, with a test in the same package, I get the following error :

java.lang.UnsupportedOperationException: cannot proxy inaccessible class class [...].AndroidCalendarGenerator.ManageEventsUI.CalendarMonitorServiceConnection
    at com.android.dx.stock.ProxyBuilder.buildProxyClass(ProxyBuilder.java:269)
    at com.android.dx.mockito.DexmakerMockMaker.createMock(DexmakerMockMaker.java:56)
    at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33)
    at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59)
    at org.mockito.Mockito.mock(Mockito.java:1285)
    at org.mockito.Mockito.mock(Mockito.java:1163)
    [...]

Here is my class :

package [...].AndroidCalendarGenerator.ManageEventsUI;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.Mockito.mock;

@RunWith(MockitoJUnitRunner.class)
public class CalendarMonitorServiceConnectionTest {

    @Test
    public void testOne() {
        CalendarMonitorServiceConnection c1 = new CalendarMonitorServiceConnection(null);
        CalendarMonitorServiceConnection c = mock(CalendarMonitorServiceConnection.class);
    }
}

I think that the first line of the test compiling without errors means that this test is in the same folder as the CalendarMonitorServiceConnection class that I try to mock.

Finally, I have those imports in my build.gradle :

androidTestCompile 'junit:junit:4.12'
androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile "com.crittercism.dexmaker:dexmaker:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-mockito:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-dx:1.4"

What am I missing ?

Thanks a lot for your answers


EDIT

Here's the code of the class I try to mock :

package [...].AndroidCalendarGenerator.ManageEventsUI;

import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.IBinder;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import [...].AndroidCalendarGenerator.CalendarEventMonitor;
import [...].AndroidCalendarGenerator.Event;
import [...].AndroidCalendarGenerator.EventChangeListener;

class CalendarMonitorServiceConnection implements ServiceConnection {

    private CalendarEventMonitor mMonitor;
    private EventListViewAdapter mEventListViewAdapter;

    CalendarMonitorServiceConnection(EventListViewAdapter eventListViewAdapter) {
        mEventListViewAdapter = eventListViewAdapter;
    }

    /**
     * Custom event change listener that defines what to do in case of changes in the calendar
     */
    private class CustomEventChangeListener implements EventChangeListener {
        @Override
        public void onEventActivated(Event event) {
            //[...]
        }

        @Override
        public void onEventRemoved(Event event) {
            //[...]
        }

        @Override
        public void onEventListChanged() {
            //[...]
        }
    }

    /**
     * Pulls data for next 30 days and send it to the adapter
     */
    private void sendNextThirtyDaysEventsToAdapter() {
        //[...]
    }

    @Override
    public void onServiceConnected(ComponentName className,
                                   IBinder service){
        //[...]
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0){
        //[...]
    }
}

Answer:

after some research, it seems to me that :

  • Mockito + Dexmaker cannot mock package-private class, even with the unit tests being in the same package.
  • Powermock can mock package-private class, but only if the unit tests are in the same package.

Therefore the solution, as I want to keep my class package-private, is to use Powermock.

Main sources :


I'll update the post as I try Powemock. Or if someone can agree or correct my answer.

Question:

Despite Mockito dependency in the testImplementation, Android Studio shows red lines complaining, it can not resolve dependency.

Below is the output of dependencies task with testImplementation as configuration.

gradle :exo-audio:dependencies --configuration testImplementation



testImplementation - Implementation only dependencies for 'test' sources. (n)
+--- junit:junit:4.12 (n)
+--- org.hamcrest:hamcrest-all:1.3 (n)
+--- org.mockito:mockito-all:1.10.19 (n)
+--- com.squareup.okhttp3:mockwebserver:4.2.1 (n)
\--- com.google.dagger:dagger:2.24 (n)

(n) - Not resolved (configuration is not meant to be resolved)

Here is the screenshot of Android Studio showing errors

I have tried cleaning build cache and invalidate restart, nothing seems to be working. Even I have also tried by removing .idea and .gradle directories manually and loading project again.

I think the problem is with Android Studio, even with studio complaining about the classes, I am able to run tests e.g. for the following test hash code is printed.

@Test
    fun foo() {
        println(repository.hashCode())
    }

Answer:

Finally! I have resolved it at the end of the day. I will list down the steps I performed.

  1. Checked test source directores and classpath in module.iml file, everything looked fine here

    <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
    
  2. Checked versions available in local gradle cache

    allaudin@geek ~/.gradle/caches/modules-2/files-2.1/org.mockito/mockito-core$ ls
    
    1.10.19  2.10.0  2.19.0  2.27.0  2.28.0  2.28.2  2.6.1  2.7.22
    

Finally I tried with different version, it didn't worked for versions till 2.10.0 and then started working for version 2.19.0.

I tried to figure out the root cause but I have to code a lot before I go to sleep. Over to experts for figuring out why some versions do not work ;)

Question:

I have a test with Mockito from my RecyclerView clicks, but an error is thrown.

This is my code:

@Test
public void getUserClick() {

    RecyclerView rcv = Mockito.mock(RecyclerView.class);
    List<User> usersList = new ArrayList<>();

    User commonUser = Mockito.mock(User.class);
    commonUser.setId("1");
    commonUser.setName("User");
    commonUser.setEmail("admin@admin.com");

    usersList.add(commonUser);

    UserAdapterTest adapter = Mockito.mock(UserAdapterTest.class);
    adapter.addData(usersList);

    rcv.setAdapter(adapter);

    // Test Click
    rcv.getChildAt(0).performClick();

    //Verify Click Item
    Mockito.verify(adapter).testClickItem(commonUser);
}

And the error launch here:

java.lang.NullPointerException in rcv.getChildAt(0).performClick();

But the IDE doesn't tell me anything else.

java.lang.NullPointerException
at com.project.test.TestRecycler.getUserClick(TestRecycler.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
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.mockito.internal.junit.JUnitRule$1.evaluateSafely(JUnitRule.java:63)
at org.mockito.internal.junit.JUnitRule$1.evaluate(JUnitRule.java:43)
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 org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

And my adapter already has the click event implemented.


Answer:

When you do:

RecyclerView rcv = Mockito.mock(RecyclerView.class);

rcv becomes a mock (an object that returns null (or 0, or false) by default, on any method call). So rcv.getChildAt(0) by default is returning null, and when you try to call performClick() on it, the NullPointerException occurs.

When you create a mock and want some method to return a specific value, you must tell it using Mockito.when(). So in your case, you should do something like this:

// configure "when" behaviour **before** calling the getChildAt() method
Mockito.when(rcv.getChildAt(0)).thenReturn(objectYouWantToBeReturned);

Obviously you need to create objectYouWantToBeReturned before using when. The code above will make rcv.getChildAt(0) returns the object you want, but only if you call it with parameter 0.

If you want to return the same object for any value (not only 0), you can do:

Mockito.when(rcv.getChildAt(Mockito.anyInt())).thenReturn(objectYouWantToBeReturned);

This will return objectYouWantToBeReturned for all calls of getChildAt, no matter what's the parameter value.