Class InlineDelegateByteBuddyMockMaker

  • All Implemented Interfaces:
    Instantiator, ClassCreatingMockMaker, InlineMockMaker, MockMaker

    @Incubating
    @SuppressSignatureCheck
    class InlineDelegateByteBuddyMockMaker
    extends java.lang.Object
    implements ClassCreatingMockMaker, InlineMockMaker, Instantiator
    Agent and subclass based mock maker.

    This mock maker which uses a combination of the Java instrumentation API and sub-classing rather than creating a new sub-class to create a mock. This way, it becomes possible to mock final types and methods. This mock maker must to be activated explicitly for supporting mocking final types and methods:

    This mock maker can be activated by creating the file /mockito-extensions/org.mockito.plugins.MockMaker containing the text mock-maker-inline or org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.

    This mock maker will make a best effort to avoid subclass creation when creating a mock. Otherwise it will use the org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker to create the mock class. That means that the following condition is true

    
     class Foo { }
     assert mock(Foo.class).getClass() == Foo.class;
     

    unless any of the following conditions is met, in such case the mock maker fall backs to the the creation of a subclass.

    Some type of the JDK cannot be mocked, this includes Class, String, and wrapper types.

    Nevertheless, final methods of such types are mocked when using the inlining mock maker. Mocking final types and enums does however remain impossible when explicitly requiring serialization support or when adding ancillary interfaces.

    Important behavioral changes when using inline-mocks:

    • Mockito is capable of mocking package-private methods even if they are defined in different packages than the mocked type. Mockito voluntarily never mocks package-visible methods within java.* packages.
    • Additionally to final types, Mockito can now mock types that are not visible for extension; such types include private types in a protected package.
    • Mockito can no longer mock native methods. Inline mocks require byte code manipulation of a method where native methods do not offer any byte code to manipulate.
    • Mockito cannot longer strip synchronized modifiers from mocked instances.

    Note that inline mocks require a Java agent to be attached. Mockito will attempt an attachment of a Java agent upon loading the mock maker for creating inline mocks. Such runtime attachment is only possible when using a JVM that is part of a JDK or when using a Java 9 VM. When running on a non-JDK VM prior to Java 9, it is however possible to manually add the Byte Buddy Java agent jar using the -javaagent parameter upon starting the JVM. Furthermore, the inlining mock maker requires the VM to support class retransformation (also known as HotSwap). All major VM distributions such as HotSpot (OpenJDK), J9 (IBM/Websphere) or Zing (Azul) support this feature.

    • Field Detail

      • INSTRUMENTATION

        private static final java.lang.instrument.Instrumentation INSTRUMENTATION
      • INITIALIZATION_ERROR

        private static final java.lang.Throwable INITIALIZATION_ERROR
      • mockitoConstruction

        private final java.lang.ThreadLocal<java.lang.Boolean> mockitoConstruction
      • currentSpied

        private final java.lang.ThreadLocal<java.lang.Object> currentSpied
    • Constructor Detail

      • InlineDelegateByteBuddyMockMaker

        InlineDelegateByteBuddyMockMaker()
    • Method Detail

      • createMock

        public <T> T createMock​(MockCreationSettings<T> settings,
                                MockHandler handler)
        Description copied from interface: MockMaker
        If you want to provide your own implementation of MockMaker this method should:
        • Create a proxy object that implements settings.typeToMock and potentially also settings.extraInterfaces.
        • You may use the information from settings to create/configure your proxy object.
        • Your proxy object should carry the handler with it. For example, if you generate byte code to create the proxy you could generate an extra field to keep the handler with the generated object. Your implementation of MockMaker is required to provide this instance of handler when MockMaker.getHandler(Object) is called.
        Specified by:
        createMock in interface MockMaker
        Type Parameters:
        T - Type of the mock to return, actually the settings.getTypeToMock.
        Parameters:
        settings - Mock creation settings like type to mock, extra interfaces and so on.
        handler - See MockHandler. Do not provide your own implementation at this time. Make sure your implementation of MockMaker.getHandler(Object) will return this instance.
        Returns:
        The mock instance.
      • createSpy

        public <T> java.util.Optional<T> createSpy​(MockCreationSettings<T> settings,
                                                   MockHandler handler,
                                                   T object)
        Description copied from interface: MockMaker
        By implementing this method, a mock maker can optionally support the creation of spies where all fields are set within a constructor. This avoids problems when creating spies of classes that declare effectively final instance fields where setting field values from outside the constructor is prohibited.
        Specified by:
        createSpy in interface MockMaker
        Type Parameters:
        T - Type of the mock to return, actually the settings.getTypeToMock.
        Parameters:
        settings - Mock creation settings like type to mock, extra interfaces and so on.
        handler - See MockHandler. Do not provide your own implementation at this time. Make sure your implementation of MockMaker.getHandler(Object) will return this instance.
        object - The object to spy upon.
        Returns:
        The spy instance, if this mock maker supports direct spy creation.
      • prettifyFailure

        private <T> java.lang.RuntimeException prettifyFailure​(MockCreationSettings<T> mockFeatures,
                                                               java.lang.Exception generationFailed)
      • resetMock

        public void resetMock​(java.lang.Object mock,
                              MockHandler newHandler,
                              MockCreationSettings settings)
        Description copied from interface: MockMaker
        Replaces the existing handler on mock with newHandler.

        The invocation handler actually store invocations to achieve stubbing and verification. In order to reset the mock, we pass a new instance of the invocation handler.

        Your implementation should make sure the newHandler is correctly associated to passed mock

        Specified by:
        resetMock in interface MockMaker
        Parameters:
        mock - The mock instance whose invocation handler is to be replaced.
        newHandler - The new invocation handler instance.
        settings - The mock settings - should you need to access some of the mock creation details.
      • clearAllCaches

        public void clearAllCaches()
        Description copied from interface: MockMaker
        Clears all cashes for mocked types and removes all byte code alterations, if possible.
        Specified by:
        clearAllCaches in interface MockMaker
      • clearMock

        public void clearMock​(java.lang.Object mock)
        Description copied from interface: InlineMockMaker
        Clean up internal state for specified mock. You may assume there won't be any interaction to the specific mock after this is called.
        Specified by:
        clearMock in interface InlineMockMaker
        Parameters:
        mock - the mock instance whose internal state is to be cleaned.
      • clearAllMocks

        public void clearAllMocks()
        Description copied from interface: InlineMockMaker
        Cleans up internal state for all existing mocks. You may assume there won't be any interaction to mocks created previously after this is called.
        Specified by:
        clearAllMocks in interface InlineMockMaker
      • isTypeMockable

        public MockMaker.TypeMockability isTypeMockable​(java.lang.Class<?> type)
        Description copied from interface: MockMaker
        Indicates if the given type can be mocked by this mockmaker.

        Mockmaker may have different capabilities in term of mocking, typically Mockito 1.x's internal mockmaker cannot mock final types. Other implementations, may have different limitations.

        Specified by:
        isTypeMockable in interface MockMaker
        Parameters:
        type - The type inspected for mockability.
        Returns:
        object that carries the information about mockability of given type.
      • createStaticMock

        public <T> MockMaker.StaticMockControl<T> createStaticMock​(java.lang.Class<T> type,
                                                                   MockCreationSettings<T> settings,
                                                                   MockHandler handler)
        Description copied from interface: MockMaker
        If you want to provide your own implementation of MockMaker this method should:
        • Alter the supplied class to only change its behavior in the current thread.
        • Only alters the static method's behavior after being enabled.
        • Stops the altered behavior when disabled.
        Specified by:
        createStaticMock in interface MockMaker
        Type Parameters:
        T - Type of the mock to return, actually the settings.getTypeToMock.
        settings - Mock creation settings like type to mock, extra interfaces and so on.
        handler - See MockHandler. Do not provide your own implementation at this time. Make sure your implementation of MockMaker.getHandler(Object) will return this instance.
        Returns:
        A control for the static mock.
      • createConstructionMock

        public <T> MockMaker.ConstructionMockControl<T> createConstructionMock​(java.lang.Class<T> type,
                                                                               java.util.function.Function<MockedConstruction.Context,​MockCreationSettings<T>> settingsFactory,
                                                                               java.util.function.Function<MockedConstruction.Context,​MockHandler<T>> handlerFactory,
                                                                               MockedConstruction.MockInitializer<T> mockInitializer)
        Description copied from interface: MockMaker
        If you want to provide your own implementation of MockMaker this method should:
        • Intercept all constructions of the specified type in the current thread
        • Only intercept the construction after being enabled.
        • Stops the interception when disabled.
        Specified by:
        createConstructionMock in interface MockMaker
        Type Parameters:
        T - Type of the mock to return, actually the settings.getTypeToMock.
        settingsFactory - Factory for mock creation settings like type to mock, extra interfaces and so on.
        handlerFactory - Factory for settings. See MockHandler. Do not provide your own implementation at this time. Make sure your implementation of MockMaker.getHandler(Object) will return this instance.
        Returns:
        A control for the mocked construction.
      • makeStandardArgument

        private java.lang.Object makeStandardArgument​(java.lang.Class<?> type)