Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot mock Google Analytics Tracker class with Inline Mocks #1000

Closed
Mykaelos opened this issue Mar 22, 2017 · 5 comments
Closed

Cannot mock Google Analytics Tracker class with Inline Mocks #1000

Mykaelos opened this issue Mar 22, 2017 · 5 comments
Labels

Comments

@Mykaelos
Copy link

Greetings,
I updated Mockito to 2.7.16 to use inline mocks for the seriously awesome feature to mock finals (thank you btw!) but found that the Google Analytics Tracker class wasn't mocking, where it was before without issue.

I found this post on the Mockito forum with the same problem, but I don't think the original reporter ever brought the issue to here.

I created a repo that can be used to reproduce the issue. You'll need Android Studio to be able to run it. The ExampleUnitTest class just tries to mock the com.google.android.gms.analytics.Tracker class and it fails right away. Here's the stack trace of that failure:

org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class com.google.android.gms.analytics.Tracker.

If you're not sure why you're getting this error, please report to the mailing list.


Java               : 1.8
JVM vendor name    : Oracle Corporation
JVM vendor version : 25.74-b02
JVM name           : Java HotSpot(TM) 64-Bit Server VM
JVM version        : 1.8.0_74-b02
JVM info           : mixed mode
OS name            : Windows 10
OS version         : 10.0


You are seeing this disclaimer because Mockito is configured to create inlined mocks.
You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.

Underlying exception : java.lang.IllegalArgumentException: Could not create type

	at com.test.mockitoanalyticstrackerbug.ExampleUnitTest.watchTrackerFailToBeMockedTest(ExampleUnitTest.java:23)
	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.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:487)
	at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:209)
	at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:109)
	at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:36)
	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.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:63)
	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)
Caused by: java.lang.IllegalArgumentException: Could not create type
	at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:140)
	at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:346)
	at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:161)
	at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:355)
	at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.mockClass(TypeCachingBytecodeGenerator.java:32)
	at org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.createMockType(InlineByteBuddyMockMaker.java:201)
	at org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.createMock(InlineByteBuddyMockMaker.java:182)
	at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:35)
	at org.mockito.internal.MockitoCore.mock(MockitoCore.java:65)
	at org.mockito.Mockito.mock(Mockito.java:1729)
	at org.mockito.Mockito.mock(Mockito.java:1642)
	... 30 more
Caused by: java.lang.VerifyError
	at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
	at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:144)
	at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.triggerRetransformation(InlineBytecodeGenerator.java:116)
	at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.mockClass(InlineBytecodeGenerator.java:96)
	at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$1.call(TypeCachingBytecodeGenerator.java:37)
	at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$1.call(TypeCachingBytecodeGenerator.java:34)
	at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:138)
	... 40 more

There's no hurry on this fix as we're not officially supporting analytics yet. I mostly just wanted to bring this to your attention as we'll need to look into this eventually and I'm sure there will be others trying to mock the Tracker. Let me know if you need more information or if there's anything I can do to help.

Thanks,
Mykaelos

@tmurakami
Copy link
Contributor

Since Tracker seems to be obfuscated by ProGuard, the class file might been broken like #1005.

I tried using -noverify option on your reproducible project.
It seems to work fine.
Try -noverify option as follows:

android {
    testOptions {
        unitTests.all {
            jvmArgs '-noverify'
        }
    }
}

@mockitoguy
Copy link
Member

Thank you for an excellent report with repository where we can reproduce the issue. 2 Mockito core developers became (are becoming) fathers this Spring so it might be a while when we have time to investigate this issue :) (ping @raphw).

In the meantime, perhaps you can follow @tmurakami advice? Thanks a lot @tmurakami for jumping in and offering help!

@raphw
Copy link
Member

raphw commented Mar 31, 2017

There should never be a verify error, I will look into this once I find the time!

@raphw
Copy link
Member

raphw commented Apr 22, 2017

I think I have this "fixed" as I added an explicit check to Byte Buddy for inconsistent stack map frames. This seems to be a side-effect of using ProGuard in Android which destroys some metainformation in a way that the JVM can still run a method but that makes it practically impossible to instrument a class.

The irony is that this destruction does not obfuscate a thing as it only removes the types of the this reference and the parameters such that they can no longer be legally accessed.

Byte Buddy does however no longer throw a verifier error but a more descriptive error message.

@TimvdLippe
Copy link
Contributor

Closing this per above comment. Feel free to reopen if you are still running into this issue with a recent Mockito version (2.10.0+)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants