This blog is about Java (advanced Java topics like Reflection, Byte Code transformation, Code Generation), Maven, Web technologies, Raspberry Pi and IT in general.

Freitag, 20. Juni 2014

Explanation how proxy based Mock Frameworks work

Have you ever wondered how these Mockito lines work?
Foo foo = Mockito.mock(Foo.class);
Yes or you are now interested? Great, then you should read this article. Otherwise you are probably lost and I can't help you. Sorry.

The first important thing to know is that there are two types of frameworks.
  1. the proxy based mock frameworks: Mockito, EasyMock, jMock, ...
  2. the mock frameworks based on bytecode manipulation: PowerMock, ...
There is a big different between those both concepts.
  1. are much easier to implement but they are more restricted in the features they can support.
  2. bytecode manipulation should tell you everything you should know about it: it's based on "very dark magic". It can break on major Java releases. So be careful if you start to use such frameworks, because they could prevent you from upgrade your Java version. PowerMock for example builds on top of Javassist. A framework which makes bytecode manipulation more simple.
In this article I will explain only how the proxy based mock frameworks like Mockito works. Because it's quite easy to understand how this kind of mock frameworks work. The knowledge will probably help you to use those frameworks if you know how they work and where the limits are. So you will never try to do anything which is technically impossible.

What is a Proxy?

A proxy is just an object which will be used instead of the original object. If a method of the proxy object is called then the proxy object can decide what it will do with this call:
  • delegate it to the original object
  • handles the call itself
Proxies can be used to implement some kind of permission system. The proxy checks if the user is allowed to call the method and if the user doesn't have the permission then it throws an exception.

A proxy doesn't require an instance of an interface/class if the proxy handles all method invocations itself.  
Mockito.mock(Foo.class) is now easily explained. This code just creates a proxy object for the Foo class.

Limits of a Proxy

There are a few important restrictions to the proxies. It's not possible to:
  • intercept static method calls
  • intercept private method calls
  • intercept final method calls
  • build a proxy for a final class
If you want to understand these limitations then read my other blog entry about: Explanation how CGLIP proxies work
Another restriction is that you have always to create the proxy explicitly. So it's not possible to say, that all Foo instances, created with new Foo() should be automatically wrapped into a proxy object. With PowerMock such things are possible. 

How to create a Proxy

If you look into the Java API you will find the java.lang.reflect.Proxy class. 
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler.
* @param   loader the class loader to define the proxy class
* @param   interfaces the list of interfaces for the proxy class to implement
* @param   h the invocation handler to dispatch method invocations to
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
It's quite simple to use. To showcase the usage of this proxy we just build our own simple mock framework - you find the complete source code at the end of the article. We create the static mock method which returns the proxy object.
public class Mock {
  public static <T> T mock(Class<T> clazz) {
    MockInvocationHandler invocationHandler = new MockInvocationHandler();
    T proxy = (T) Proxy.newProxyInstance(Mock.class.getClassLoader(), new Class[]{clazz}, invocationHandler);
    return proxy;

This creates a proxy object for the clazz and redirects all calls to the MockInvocationHandler which looks like this:

private static class MockInvocationHandler implements InvocationHandler {
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    return null;
So each call to a method of the proxy object will return null. At this stage we have an proxy object on which we can call methods. 

How to dynamically define the Proxy?

Now the question is how to setup the proxy to return something else than just null. We need to do something like: Mock.when(foo.echo("foo")).thenReturn("foo")

But how does this work? To understand how this work you have to analyze the one line of code very carefully and think about what it actually does. 

What does the when() method actually gets?

In the case of our example it would just gets a null object. In the first step we created the foo object which is a proxy which always return null. The when() method doesn't get the method echo() with a parameter. It's an common method call. It's a call to the proxy which will return null and pass the null value to the when() method. That's it. 

How the thenReturn() method works?

You have learned that the when() method just got null. So how can the thenReturn() call work? Think a few minutes about it. It's nothing special. It can be called at most "a little trick".

The solution is simple: with static variables in which the state is stored.
  • in the MockInvocationHandler we store the method and the arguments of the last call
  • in the Mock class - Mock.when(foo.echo("foo")).thenReturn("foo") - we store the reference to the MockInvocationHandler which was called last
These two steps happens in the invoke() method of the proxy object - in the MockInvocationHandler. The when() method doesn't have any logic. When thenReturn() is called then we store the return value for the stored (remembered) MockInvocationHandler with it's last method and arguments. If the proxy is called again then it will return the stored return value (if it's the same method gets called with the same parameter).

Basically that's it

I hope you could follow so far. I will summarize it again with other words
  • create a proxy
  • if a proxy method is called then remember which method was called. This proxy method call is normally located inside of the Mock.when() method - even if it has no relationship to the when() method.
  • if thenReturn(value) is called store the "value" to the stored/remembered method.
  • the proxy returns the "value" if the method is called again with the correct arguments.

The genius behind this is

The very simple API which makes the whole thing looks like very nice. Another great decision is that the when() method uses generics so that the thenReturn() method is type safe.

But what's about classes?

The current solution only works for interfaces. Because java.lang.reflect.Proxy only supports interfaces and not classes. So we need another mechanism to create the proxy. We have to dig a little be deeper and finally come to CGLIB - Code Generation Library. So we are back to magic. But it's by far not so dangerous like bytecode manipulation. We just use bytecode generation to create the proxy which shouldn't fail. In fact many tools are using CGLIB (e.g. Spring, Hibernate).

To create a proxy with CGLIB isn't any more difficult than with the Java`s Proxy class.
public static <T> T mock(Class<T> clazz) {
  Enhancer enhancer = new Enhancer();
  enhancer.setCallback(new MockMethodInterceptor());
  return (T) enhancer.create();

private static class MockMethodInterceptor {
  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    return null;
That's it. Everything else stays the same.
With this kind of proxy you can easily build something like
Foo foo = new Foo();
foo = Mockito.spy(foo);
You can create a proxy for a real object. All calls will be delegated to the real object expect if the method call is redefined. With CGLIB this is very easy to build. If you want to know more just take a look at the source code. 

Source Code

A simple mock framework to demonstrate how the proxy based mock frameworks work. With two implementations:
  • based on the java.lang.reflect.Proxy.
  • based on CGLIB. The CGLIB mock also implements the spy method.
Checkout the code from

18 Kommentare:

  1. Antworten
    1. The development of artificial intelligence (AI) has propelled more programming architects, information scientists, and different experts to investigate the plausibility of a vocation in machine learning. Notwithstanding, a few newcomers will in general spotlight a lot on hypothesis and insufficient on commonsense application. machine learning projects for final year In case you will succeed, you have to begin building machine learning projects in the near future.

      Projects assist you with improving your applied ML skills rapidly while allowing you to investigate an intriguing point. Furthermore, you can include projects into your portfolio, making it simpler to get a vocation, discover cool profession openings, and Final Year Project Centers in Chennai even arrange a more significant compensation.

      Data analytics is the study of dissecting crude data so as to make decisions about that data. Data analytics advances and procedures are generally utilized in business ventures to empower associations to settle on progressively Python Training in Chennai educated business choices. In the present worldwide commercial center, it isn't sufficient to assemble data and do the math; you should realize how to apply that data to genuine situations such that will affect conduct. In the program you will initially gain proficiency with the specialized skills, including R and Python dialects most usually utilized in data analytics programming and usage; Python Training in Chennai at that point center around the commonsense application, in view of genuine business issues in a scope of industry segments, for example, wellbeing, promoting and account.

      The Nodejs Projects Angular Training covers a wide range of topics including Components, Angular Directives, Angular Services, Pipes, security fundamentals, Routing, and Angular programmability. The new Angular TRaining will lay the foundation you need to specialise in Single Page Application developer. Angular Training

  2. Nice article precisely explained.

  3. I never thought I will be able to understand mockito this much easily. Thank you so much.

  4. I hope really like this wonderful information to share here. Thanks for the sharing your idea.
    Java Online Training
    Python Online Training
    PHP Online Training

  5. Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
    blockchain online training
    best blockchain online training
    top blockchain online training

  6. I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously
    in their life, he/she can earn his living by doing blogging.Thank you for this article.
    java online training

  7. I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously
    in their life, he/she can earn his living by doing blogging.Thank you for this article.
    best java online training

  8. I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously
    in their life, he/she can earn his living by doing blogging.Thank you for this article.
    best java online training