easyforgood / mockito

Automatically exported from code.google.com/p/mockito
0 stars 0 forks source link

Having dexmaker in my Android project prevents junit tests from running w/o Android #406

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
1. Create an android test project with test that use Mockito
2. Include mockito 1.9.5, dexmaker 1.0, and dexmaker-android 1.0 jars
3. Run the test on an Android device in eclipse using Run As -> Android JUnit 
Test (it works)
4. Try to run the test locally in eclipse using Run As -> JUnit Test and use 
the Android test runner.

I expect the test to also work (assuming it uses no Android APIs, which it does 
not).  Instead I get this:

java.lang.ExceptionInInitializerError
at 
org.mockito.internal.creation.jmock.ClassImposterizer.createProxyClass(ClassImpo
sterizer.java:85)
at 
org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposteri
zer.java:62)
at 
org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposteri
zer.java:56)
at 
org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51)
at org.mockito.Mockito.mock(Mockito.java:1243)
at 
org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotatio
nProcessor.java:30)
at 
org.mockito.internal.configuration.MockAnnotationProcessor.process(MockAnnotatio
nProcessor.java:16)
at 
org.mockito.internal.configuration.DefaultAnnotationEngine.createMockFor(Default
AnnotationEngine.java:43)
at 
org.mockito.internal.configuration.DefaultAnnotationEngine.process(DefaultAnnota
tionEngine.java:66)
at 
org.mockito.internal.configuration.InjectingAnnotationEngine.processIndependentA
nnotations(InjectingAnnotationEngine.java:71)
at 
org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAn
notationEngine.java:55)
at org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:108)
at MyTest.setUp(MyTest.java:63)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)
at 
android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:55
5)
at 
android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1584)
Caused by: java.lang.VerifyError: org/mockito/cglib/core/ReflectUtils
at 
org.mockito.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:167)
at 
org.mockito.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrateg
y.java:25)
at 
org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java
:217)
at org.mockito.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:117)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:109)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:105)
at org.mockito.cglib.proxy.Enhancer.<clinit>(Enhancer.java:70)
... 24 more

Apparently, when dexmaker is in the classpath, Mockito sees it as an extension 
and just assumes it should be used, which is an incorrect assumption if not 
running on Dalvik.  If I remove the dexmaker jars from the test project, I can 
unit test just fine locally (but no longer on Dalvik).  I can't find an easy 
way to prevent this manual step so that I can test seamlessly on both Android 
and locally.

It would be awesome if Mockito would NOT use dexmaker if we're not in a Dalvik 
environment.  As a workaround, I would like to know the code that directly 
disables the dexmaker extension so I can disable it myself when running tests.  
It is a huge win for TDD to be able to run tests locally without needing a 
device or slow emulator.  It is also a huge win for me to run my automated 
tests during continuous integration against an emulator to verify the final 
product.

Original issue reported on code.google.com by beafd...@gmail.com on 18 Dec 2012 at 7:51

GoogleCodeExporter commented 8 years ago
Hi,

Interesting idea. However I'm not sure we want to list all possible JVMs. In 
the mean time could it be possible to add the dependency in the classpath 
wether you are targeting a JVM or the device ?

Note that at the moment noone in the team actually develop on Android, you 
might want to get in touch with the google guys. As a lazy developer, or 
overwhelmed by real life, I believe the Dexmaker project could fallback to the 
default MockMacker if they detect a standard JVM.

Thanks for reporting the idea, also if you have a technical proposal we could 
look into it and see how it fits in the project.

Cheers,
Brice 

Original comment by brice.du...@gmail.com on 19 Dec 2012 at 10:57

GoogleCodeExporter commented 8 years ago

Original comment by brice.du...@gmail.com on 19 Dec 2012 at 10:59

GoogleCodeExporter commented 8 years ago
Related to dexmaker issue 5 : 
https://code.google.com/p/dexmaker/issues/detail?id=5

Original comment by brice.du...@gmail.com on 4 Dec 2013 at 3:06

GoogleCodeExporter commented 8 years ago
Any workaround for this? we are trying to use mockito both in the JVM and 
Dalvik depending on the type of tests we run.

Is there a way of telling mockito not to use dexmaker?

Original comment by iva...@gmail.com on 11 Nov 2014 at 3:48

GoogleCodeExporter commented 8 years ago
Mockito has no mechanism right now on that matter.

Maybe something is achievable on with gradle to tweak the classpath depending 
on some properties / profiles, etc...

Original comment by brice.du...@gmail.com on 12 Nov 2014 at 1:22

GoogleCodeExporter commented 8 years ago
This is an awful workaround, but if your (jvm) robolectric test are run with 
the task 'testDebug' and your (dalvik) espresso ones are run with another task, 
you can add this to your build.gradle file:

//remove dex maker if running robolectric, as they don't agree with other
project.tasks.whenTaskAdded { task ->
    if (task.name.equals("testDebug")) {
        def removeDexmakerDependency = project.tasks.create(name: "removeDexmakerDependency",) {
            project.configurations.androidTestCompile.dependencies.all { dependency ->
                if (dependency.name.startsWith("dexmaker")) {
                    project.configurations.androidTestCompile.dependencies.remove(dependency)
                }
            }
        }

        task.dependsOn removeDexmakerDependency
    }
}

Original comment by jasond...@gmail.com on 5 Dec 2014 at 4:14

GoogleCodeExporter commented 8 years ago
Hey guys,

Mockito 1.10.15 contains a new extension point: PluginSwitch. 
https://github.com/mockito/mockito/blob/master/doc/release-notes/official.md#110
15-2014-12-12-2342-utc

It can be used to switch off dexmaker's PluginSwitch if we're not running in 
dalvik. The plugin does not is not documented greatly yet (contributions 
welcome!) but it should be already useful.

This plugin can be implemented and included in dexmaker distribution to solve 
this use case out of the box (contributions welcome!). Until this happens, 
users can drop their own impl of this plugin on the the classpath.

Original comment by szcze...@gmail.com on 13 Dec 2014 at 5:31

GoogleCodeExporter commented 8 years ago
I'm closing this issue. Please use GitHub for new queries or when following up 
on this ticket. Thanks!

Original comment by szcze...@gmail.com on 13 Dec 2014 at 5:32