Class AcrossJVMSerializationFeature

java.lang.Object
org.powermock.api.mockito.repackaged.AcrossJVMSerializationFeature
All Implemented Interfaces:
Serializable

@Incubating class AcrossJVMSerializationFeature extends Object implements Serializable
This is responsible for serializing a mock, it is enabled if the mock is implementing Serializable.

The way it works is to enable serialization via the enableSerializationAcrossJVM(MockCreationSettings), if the mock settings is set to be serializable it will add the AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable interface. This interface defines a the AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable.writeReplace() whose signature match the one that is looked by the standard Java serialization.

Then in the MethodInterceptorFilter of mockito, if the writeReplace method is called, it will use the custom implementation of this class writeReplace(Object). This method has a specific knowledge on how to serialize a mockito mock that is based on CGLIB.

Only one instance per mock! See MethodInterceptorFilter

TODO use a proper way to add the interface TODO offer a way to disable completely this behavior, or maybe enable this behavior only with a specific setting TODO check the class is mockable in the deserialization side
Since:
1.10.0
See Also:
  • CglibMockMaker
  • MethodInterceptorFilter
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      See Also:
    • MOCKITO_PROXY_MARKER

      private static final String MOCKITO_PROXY_MARKER
      See Also:
    • instanceLocalCurrentlySerializingFlag

      private boolean instanceLocalCurrentlySerializingFlag
    • mutex

      private final Lock mutex
  • Constructor Details

    • AcrossJVMSerializationFeature

      AcrossJVMSerializationFeature()
  • Method Details

    • isWriteReplace

      public boolean isWriteReplace(Method method)
    • writeReplace

      public Object writeReplace(Object mockitoMock) throws ObjectStreamException
      Custom implementation of the writeReplace method for serialization. Here's how it's working and why :
      1. When first entering in this method, it's because some is serializing the mock, with some code like :

        
             objectOutputStream.writeObject(mock);
         
        So, ObjectOutputStream will track the writeReplace method in the instance and execute it, which is wanted to replace the mock by another type that will encapsulate the actual mock. At this point, the code will return an AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy.

      2. Now, in the constructor AcrossJVMMockSerializationProxy(Object) the mock is being serialized in a custom way (using AcrossJVMSerializationFeature.MockitoMockObjectOutputStream) to a byte array. So basically it means the code is performing double nested serialization of the passed mockitoMock.

        However the ObjectOutputStream will still detect the custom writeReplace and execute it. (For that matter disabling replacement via ObjectOutputStream.enableReplaceObject(boolean) doesn't disable the writeReplace call, but just just toggle replacement in the written stream, writeReplace is always called by ObjectOutputStream.)

        In order to avoid this recursion, obviously leading to a StackOverflowError, this method is using a flag that marks the mock as already being replaced, and then shouldn't replace itself again. This flag is local to this class, which means the flag of this class unfortunately needs to be protected against concurrent access, hence the reentrant lock.

      Parameters:
      mockitoMock - The Mockito mock to be serialized.
      Returns:
      A wrapper (AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy) to be serialized by the calling ObjectOutputStream.
      Throws:
      ObjectStreamException
    • mockReplacementCompleted

      private void mockReplacementCompleted()
    • mockReplacementStarted

      private void mockReplacementStarted()
    • mockIsCurrentlyBeingReplaced

      private boolean mockIsCurrentlyBeingReplaced()
    • enableSerializationAcrossJVM

      public <T> void enableSerializationAcrossJVM(org.mockito.mock.MockCreationSettings<T> settings)
      Enable serialization serialization that will work across classloaders / and JVM.

      Only enable if settings says the mock should be serializable. In this case add the AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable to the extra interface list.

      Type Parameters:
      T - Type param to not be bothered by the generics
      Parameters:
      settings - Mock creation settings.