Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does "static reflection" work in java? (ex. in mockito or easymock)

I'm a .NET guy - and I mainly code in C#.

Since C# 3.0, we can leverage lambda expressions and expression trees to use static reflection. For example, it is possible to implement GetMethodName in the following snippet to return the name of the method passed in parameter:

string methodName = GetMethodName( o => o.DoSomething());
Console.WriteLine(methodName); // displays "DoSomething"

Now, when I look at Mockito samples (or EasyMock ones) in the java world, I see:

LinkedList mockedList = mock(LinkedList.class);
when(mockedList.get(0)).thenReturn("first");

How does it work?

How does the when method work ? How does it interpret mockedList.get(0) as a call to the get method with 0 passed as parameter and not as a value?

like image 544
Romain Verdier Avatar asked Mar 09 '09 13:03

Romain Verdier


2 Answers

Mocking libraries don't typically work with expression trees. They build a type which implements the appropriate interface and responds to method calls either by recording them or validating them and returning the preprogrammed responses. This is usually done with either a proxy (e.g. RealProxy in .NET, Proxy in Java) or with dynamic code generation.

In the case of EasyMock, it uses Proxy (for interfaces, anyway), as you can see in the source code: look at org.easymock.internal.JavaProxyFactory.

like image 70
Jon Skeet Avatar answered Oct 18 '22 09:10

Jon Skeet


Java mock libraries usually work like this:

When you create a mock, an actual proxy is created (be it from an interface or a sub-class), the instance is in "recording mode". This means that any subsequent call is recorded (method name, parameters, return expected). Notice that the proxy in recording mode does actually nothing but record the calls. There is no reflection per-se involved. No metadata discovery, etc. Of course these libraries do some tricks (such as storing invocations in a thread-local variable to handle methods that return void) but the idea remains the same.

Then, when the "replay mode" is started, the mock instance simply checks the expectations from the list of invocations (method+parameters & return values).

like image 43
Antonio Avatar answered Oct 18 '22 07:10

Antonio