Mockito created a proxy object to intercept the operations that sent originally to the real object, there is no class or object manipulation involved, it uses cglib or byte buddy as mocker to help managing the proxy object, because it dose not do any lass or object manipulation, it has some limitations like can not mock final class, can not mock static method etc. But I would say it is just by design of Mockito, nothing wrong on the Mockito itself, since you can find some other way like minor code refactoring on your business code to do the test-driven development without need to mock private class or static method.
Mockito is a mock/stub framework, it manages mock/stub logics so that test developers can conveniently uses when/then/verify syntax to mock real logic during unit testing. The proxy object’s functionality is done through third party frameworks. It internally uses the CGLIB or Byte Buddy as mocker to define and instantiate proxy object which either uses same interface as real object or extend the the class of the real object.
Mockito defines interface called MockingProgress, it works as coordinator between stub operations and proxy objects. The stub object here is abstracted by Mockito by using interfaces like IOngoingStubbing, the detailed mock rules are registered into InvocationContainer which is managed by stub object.
When you call Mockito.mock to start declare a mock object, Mockito uses mocker library internally to create a proxy object and then register the mocked object into mocked object list.
The general mock syntax like when(xxx).thenReturn(xxx) is done by calling IOngoingStubbing methods to configure the mocking detailed rules which are associated with the mocked proxy objects with help of the coordinator class MockingProgress.
When the proxy object gets called during test, the interceptor handler that inside the proxy object uses the call arguments and checks the invocation rules that registered earlier to implement the real mocking logic.
for the mockers you can check details on CGLib and Byte Buddy.
Byte Buddy https://github.com/raphw/byte-buddy
Powermock dose the mock in more aggressive way, it uses custom class loader and manipulates class byte code so that testers can do the mock on a lot more things like static method, private method, constructors and even static initializer. Powermock is actually superset of Mockito, for object or instance mock, it can theoretically can use same proxy mechanism as Mockitor dose. Because Powermock shares same usage style as Mockito, most of the time, we do not feel the major switch between the 2 mock frameworks. We do object level mock by using Mockito and then do the class level mock or something more aggressive mock that Mockito can not do using Powermock.
When a class (the test class by default) is annotated with @PrepareForTest then the class will be loaded by PowerMock custom class loader, when the class is loaded through the custom class loader, Powermock manipulates the class byte code with the changes that Powermock later can conveniently dose the mocks.
The objetFactory will be configured into the unit test engine like TestNG, so every time test engine ask for test class or test object instantiation the Powermock’s custom class loader is used.
With help of the custom PowerMock class loader, PowerMock can then work with test cases to do the real stub/mock logics. Class MockCreator is the entry point for all mocks, it internally uses MockRepository to register the mock rules into the manipulated class or the instances that instantiated by the manipulated class.
When those mock rules are registered and stored inside MockRespository class, The stub class of PowerMock will associate the mock rules into each mock stub, it is very similar as Mockito. Actually the object level mock logic, PowerMock seems integrate the Mockito classes to manage some proxy object creation hand interception handler injection.