question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

bug: mockito-android crashes instead of warning when running unit tests

See original GitHub issue

Bug report

We are seeing a strange crash coming from AndroidByteBuddyMockMaker when calling Mockito.mock in unit tests. It appears that it’s crashing because it is trying to use the PluginRegistry logger during initialization of the registry: PluginRegistry field on Plugins.

It’s pretty clear looking at the code in AndroidByteBuddyMockMaker that the intended behavior is for a warning to be issued, but instead it crashes with a somewhat garbled error (pasted below).

This only happens when you include mockito-android in the classpath when running unit tests. This is normally a problem solvable by the user, except there appears to be a bug in Android Studio 3.4.0 where switching back and forth between build variants adds androidTestImplementation dependencies to the classpath even for unit tests 🤷‍♂.

(We plan to open a separate bug report with Android Studio to cover that)

Versions

mockito: 2.27.0 android studio: 3.4.0 jre: 1.8.0_152 x86

Steps to Repro

  • create a new gradle project with testImplementation("org.mockito:mockito-android:2.27.0") in dependencies
  • create a unit test with the following code:
package com.example.mockitoandroidcrash

import org.junit.Test

import org.junit.Assert.*
import org.mockito.Mockito.mock

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * See [testing documentation](http://d.android.com/tools/testing).
 */
class ExampleUnitTest {
    open class Example

    @Test
    fun `uses default SubclassByteBuddyMockMaker for mocking`() {
        val exampleMock = mock(Example::class.java)
        assertTrue(exampleMock is Example)
    }
}
  • Run the test for ExampleUnitTest

Expected Behavior

  • the test should should run and pass, but log a warning message:
IMPORTANT NOTE FROM MOCKITO:

You included the 'mockito-android' dependency in a non-Android environment.
The Android mock maker was disabled. You should only include the latter in your 'androidTestCompile' configuration
If disabling was a mistake, you can set the 'org.mockito.mock.android' property to 'true' to override this detection.

Visit https://javadoc.io/page/org.mockito/mockito-core/latest/org/mockito/Mockito.html#0.1 for more information

Actual Behavior

  • It fails the test, crashing with the following error message and stack trace:
java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)

	at org.mockito.internal.configuration.plugins.PluginLoader$1.invoke(PluginLoader.java:74)
	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:240)
	at org.mockito.internal.creation.MockSettingsImpl.build(MockSettingsImpl.java:228)
	at org.mockito.internal.MockitoCore.mock(MockitoCore.java:61)
	at org.mockito.Mockito.mock(Mockito.java:1907)
	at org.mockito.Mockito.mock(Mockito.java:1816)
	at com.example.mockitoandroidcrash.ExampleUnitTest.uses default SubclassByteBuddyMockMaker for mocking(ExampleUnitTest.kt:18)
	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.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.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 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.IllegalStateException: Failed to load interface org.mockito.plugins.MockMaker implementation declared in sun.misc.CompoundEnumeration@57fa26b7
	at org.mockito.internal.configuration.plugins.PluginInitializer.loadImpl(PluginInitializer.java:54)
	at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:57)
	at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:44)
	at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:22)
	at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:19)
	at org.mockito.internal.util.MockUtil.<clinit>(MockUtil.java:24)
	... 37 more
Caused by: java.lang.NullPointerException
	at org.mockito.internal.configuration.plugins.Plugins.getMockitoLogger(Plugins.java:66)
	at org.mockito.android.internal.creation.AndroidByteBuddyMockMaker.<init>(AndroidByteBuddyMockMaker.java:24)
	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.PluginInitializer.loadImpl(PluginInitializer.java:49)
	... 42 more

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:10
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

4reactions
TimvdLippecommented, Apr 30, 2019

This is working as intended. You need to add mockito-android in the androidTestImplementation scope per our documentation: https://static.javadoc.io/org.mockito/mockito-core/2.27.0/org/mockito/Mockito.html#0.1

diff --git a/app/build.gradle b/app/build.gradle
index 5703b96..c7c2c27 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -27,8 +27,8 @@ dependencies {
     implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
     implementation 'com.android.support:appcompat-v7:28.0.0'
     testImplementation 'junit:junit:4.12'
-    testImplementation("org.mockito:mockito-core:2.27.0")
-    testImplementation("org.mockito:mockito-android:2.27.0")
+    testImplementation "org.mockito:mockito-core:2.27.0"
+    androidTestImplementation "org.mockito:mockito-android:2.27.0"
     androidTestImplementation 'com.android.support.test:runner:1.0.2'
     androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
 }
 ./gradlew clean && ./gradlew :app:testDebugUnitTest

> Configure project :app
BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 executed

> Configure project :app

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.1.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 2s
16 actionable tasks: 15 executed, 1 up-to-date
1reaction
tlubzcommented, Apr 30, 2019

My reading of the code in AndroidByteBuddyMockMaker seems to be that if you do load mockito-android in a unit test, it should log a warning and delegate to the default MockMaker implementation, not raise an exception.

A separate issue, which is what led to me discovering this in the first place, is that Android Studio 3.4.0 doesn’t seem to be doing the right thing when running tests in the IDE: it’s sometimes loading androidTestImplementation dependencies during unit test runs.

Assuming you’ve changed testImplementation to androidTestImplementation, you can still reproduce this crash: open the project in Android Studio 3.4.0 (currently the latest stable build), click on “Build Variants” on the left bar, and switch the variant to “release”, then run the ExampleUnitTest test. It is failing for me with the error in the issue description.

Hopefully this helps.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Log messages in android studio junit test - Stack Overflow
If the code you are testing contains Log.x static calls and your unit tests do not crash - you have a problem. I'd...
Read more >
Android Unit Testing, Mockito, and Modular Code - YouTube
Let me show you want building an Android App is like! WARNING : I sometimes swear (in multiple languages) and make off-color jokes....
Read more >
Hilt testing guide | Android Developers
This makes Hilt work for all of the instrumented tests in your project. Perform the following steps:
Read more >
Mockito 3.3.0 API - javadoc.io
To enable Android support, add the `mockito-android` library as dependency to ... You can continue to run the same unit tests on a...
Read more >
Full Guide to Testing Android Applications in 2022
First, we will tackle Unit tests that test individual small parts of our application ... Now, if we run this test, we will...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found