public static class AcrossJVMSerializationFeature.MockitoMockObjectInputStream
extends java.io.ObjectInputStream
ObjectInputStream that will resolve the Mockito proxy class.
This specificaly crafted ObjectInoutStream has the most important role to resolve the Mockito generated
class. It is doing so via the resolveClass(java.io.ObjectStreamClass) which looks in the stream
for a Mockito marker. If this marker is found it will try to resolve the mockito class otherwise it
delegates class resolution to the default super behavior.
The mirror method used for serializing the mock is
AcrossJVMSerializationFeature.MockitoMockObjectOutputStream.annotateClass(Class).
When this marker is found, org.mockito.internal.creation.cglib.ClassImposterizer methods are being used to create the mock class.
Note that behind the ClassImposterizer there is CGLIB and the
SearchingClassLoader that will look if this enhanced class has
already been created in an accessible classloader ; so basically this code trusts the ClassImposterizer
code.
| Modifier and Type | Field and Description |
|---|---|
private java.util.Set<java.lang.Class> |
extraInterfaces |
private java.lang.Class |
typeToMock |
baseWireHandle, PROTOCOL_VERSION_1, PROTOCOL_VERSION_2, SC_BLOCK_DATA, SC_ENUM, SC_EXTERNALIZABLE, SC_SERIALIZABLE, SC_WRITE_METHOD, STREAM_MAGIC, STREAM_VERSION, SUBCLASS_IMPLEMENTATION_PERMISSION, SUBSTITUTION_PERMISSION, TC_ARRAY, TC_BASE, TC_BLOCKDATA, TC_BLOCKDATALONG, TC_CLASS, TC_CLASSDESC, TC_ENDBLOCKDATA, TC_ENUM, TC_EXCEPTION, TC_LONGSTRING, TC_MAX, TC_NULL, TC_OBJECT, TC_PROXYCLASSDESC, TC_REFERENCE, TC_RESET, TC_STRING| Constructor and Description |
|---|
MockitoMockObjectInputStream(java.io.InputStream in,
java.lang.Class typeToMock,
java.util.Set<java.lang.Class> extraInterfaces) |
| Modifier and Type | Method and Description |
|---|---|
private void |
hackClassNameToMatchNewlyCreatedClass(java.io.ObjectStreamClass descInstance,
java.lang.Class<?> proxyClass)
Hack the
name field of the given ObjectStreamClass with
the newProxyClass. |
private boolean |
notMarkedAsAMockitoMock(java.lang.Object marker)
Read the stream class annotation and identify it as a Mockito mock or not.
|
protected java.lang.Class<?> |
resolveClass(java.io.ObjectStreamClass desc)
Resolve the Mockito proxy class if it is marked as such.
|
available, close, defaultReadObject, enableResolveObject, read, read, readBoolean, readByte, readChar, readClassDescriptor, readDouble, readFields, readFloat, readFully, readFully, readInt, readLine, readLong, readObject, readObjectOverride, readShort, readStreamHeader, readUnshared, readUnsignedByte, readUnsignedShort, readUTF, registerValidation, resolveObject, resolveProxyClass, skipBytesprivate final java.lang.Class typeToMock
private final java.util.Set<java.lang.Class> extraInterfaces
public MockitoMockObjectInputStream(java.io.InputStream in,
java.lang.Class typeToMock,
java.util.Set<java.lang.Class> extraInterfaces)
throws java.io.IOException
java.io.IOExceptionprotected java.lang.Class<?> resolveClass(java.io.ObjectStreamClass desc)
throws java.io.IOException,
java.lang.ClassNotFoundException
Uses the fields typeToMock and extraInterfaces to
create the Mockito proxy class as the ObjectStreamClass
doesn't carry useful information for this purpose.
resolveClass in class java.io.ObjectInputStreamdesc - Description of the class in the stream, not used.java.io.IOExceptionjava.lang.ClassNotFoundExceptionprivate void hackClassNameToMatchNewlyCreatedClass(java.io.ObjectStreamClass descInstance,
java.lang.Class<?> proxyClass)
throws java.io.ObjectStreamException
name field of the given ObjectStreamClass with
the newProxyClass.
The parent ObjectInputStream will check the name of the class in the stream matches the name of the one
that is created in this method.
The CGLIB classes uses a hash of the classloader and/or maybe some other data that allow them to be
relatively unique in a JVM.
When names differ, which happens when the mock is deserialized in another ClassLoader, a
java.io.InvalidObjectException is thrown, so this part of the code is hacking through
the given ObjectStreamClass to change the name with the newly created class.descInstance - The ObjectStreamClass that will be hacked.proxyClass - The proxy class whose name will be applied.java.io.InvalidObjectExceptionjava.io.ObjectStreamExceptionprivate boolean notMarkedAsAMockitoMock(java.lang.Object marker)
throws java.io.IOException,
java.lang.ClassNotFoundException
marker - The marker to identify.true if not marked as a Mockito, false if the class annotation marks a Mockito mock.java.io.IOExceptionjava.lang.ClassNotFoundException