Hot questions for Using Mockito in 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:
- Do I first need to download Mockito manually?
- 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 :
- Mocking package private classes
- Provide mock for package-private class?
- My own testing
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.
Checked
test source directores
andclasspath
in module.iml file, everything looked fine here<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
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.