@Incubating public class InlineByteBuddyMockMaker extends Object
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:
java.*
packages.native
methods. Inline mocks require byte code manipulation of a
method where native methods do not offer any byte code to manipulate.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.
MockMaker.TypeMockability
Constructor and Description |
---|
InlineByteBuddyMockMaker() |
Modifier and Type | Method and Description |
---|---|
<T> T |
createMock(MockCreationSettings<T> settings,
MockHandler handler)
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. |
<T> Class<? extends T> |
createMockType(MockCreationSettings<T> settings) |
MockHandler |
getHandler(Object mock)
Returns the handler for the
mock . |
MockMaker.TypeMockability |
isTypeMockable(Class<?> type)
Indicates if the given type can be mocked by this mockmaker.
|
void |
resetMock(Object mock,
MockHandler newHandler,
MockCreationSettings settings)
Replaces the existing handler on
mock with newHandler . |
public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler)
MockMaker
MockMaker
this method should:
settings.typeToMock
and potentially also settings.extraInterfaces
.settings
to create/configure your proxy object.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.
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.public <T> Class<? extends T> createMockType(MockCreationSettings<T> settings)
public MockHandler getHandler(Object mock)
MockMaker
mock
. Do not provide your own implementations at this time
because the work on the MockHandler
api is not completed.
Use the instance provided to you by Mockito at MockMaker.createMock(org.mockito.mock.MockCreationSettings<T>, org.mockito.invocation.MockHandler)
or MockMaker.resetMock(java.lang.Object, org.mockito.invocation.MockHandler, org.mockito.mock.MockCreationSettings)
.mock
- The mock instance.public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings)
MockMaker
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
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.public MockMaker.TypeMockability isTypeMockable(Class<?> type)
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.
type
- The type inspected for mockability.Copyright © 2023. All rights reserved.