linkedin / dexmaker

A utility for doing compile or runtime code generation targeting Android's Dalvik VM
Apache License 2.0
1.86k stars 248 forks source link

Support serialization of Mockito mocks #56

Open surlac opened 7 years ago

surlac commented 7 years ago

I'm writing a unit-test for Android app, which creates a mock of serializable custom class and tries to serialize it. It works fine in JUnit test when I'm running it in JVM, but fails with following error when I'm running it as Android test in emulator:

Full gist of error message.

W/System.err: java.io.NotSerializableException: com.android.dx.mockito.InvocationHandlerAdapter
W/System.err:     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1224)
W/System.err:     at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1584)
W/System.err:     at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1549)
W/System.err:     at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1472)

Here is my code (Android test gist):

Entity serializableMock = mock(Entity.class, Mockito.withSettings().serializable());
try {
    ObjectOutputStream out = new ObjectOutputStream(new ByteArrayOutputStream());
    out.writeObject(serializableMock);
} catch (IOException e) {//catching NotSerializableException here} 

Entity:

package org.test;
public class Entity implements Serializable {
    public String str;
    // getters/setters
}

Gradle dependencies:

androidTestCompile 'org.mockito:mockito-core:2.4.0'
androidTestCompile 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0'
androidTestCompile "com.android.support:support-annotations:25.0.0"
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'

How to properly serialize mock object on Android?

drewhannay commented 7 years ago

@rsharifu Does this issue still happen if you remove androidTestCompile 'org.mockito:mockito-core:2.4.0' and use the default version of mockito that dexmaker depends on? I haven't tested dexmaker with Mockito 2.4 yet.

surlac commented 7 years ago

@drewhannay I run the test again, the issue still exists even after removing androidTestCompile 'org.mockito:mockito-core:2.4.0'. Here is the list of dependencies after removal:

byte-buddy-1.5.5
byte-buddy-agent-1.5.5
dalvik-dx-7.1.0_r7
dexmaker-2.2.0
dexmaker-mockito-2.2.0
exposed-instrumentation-api-publish-0.5
hamcrest-core-1.3
junit-4.12
libcore-dex-7.1.0_r7
mockito-core-2.2.29
objenesis-2.4
rules-0.5
runner-0.5
support-annotations-25.0.0
drewhannay commented 7 years ago

Thanks for the extremely detailed report, this is incredibly helpful.

I spent some time investigating this and it looks like serialization support is a feature of JVM Mockito that was never implemented in dexmaker. It seems like this will be non-trivial to implement and I don't know how quickly I can get to it, so I'm going to edit the description of this issue to note that this is a missing feature request.

engintekin commented 7 years ago

@drewhannay would it be a hack to make com.android.dx.mockito.InvocationHandlerAdapter Serializable?

drewhannay commented 7 years ago

That was my first try. 😉

I don't think that will work though...the actual code needed to make serializable mocks behave as expected is pretty complex. It may be worth checking out the new mockito-android project from the mockito team if this is important to you.