views:

920

answers:

4

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?

+1  A: 

I’ve never worked with mockito or easymock but I don’t think the call does what you think it does. It does not interpret mockedList.get(0) in any special way. The method get is executed on the mockedList object normally, and the result of that is handed in to when.

Bombe
+1  A: 

mockedList.get(0) is the syntax for a method call, and does exactly that. What that method does is not exactly clear. mockedList's runtime type will be a subclass of LinkedList returned by the mock method, which can be implemented how ever the mocking framework sees fit.

Tom Hawtin - tackline
+3  A: 

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.

Jon Skeet
Proxy on works with interfaces. Real mocking frameworks to their own code generation.
Tom Hawtin - tackline
Romain Verdier
Rhino Mocks existed long before expression trees did. It may use expression trees *now* in some cases, but it doesn't *always* do so. (It still works in .NET 2.0.) If you make another call to the mock before specifying the result of the last one, the results depend on the mode of the mock.
Jon Skeet
(IIRC, anyway.) In a strict mode, the recording phase will fail because you haven't specified the appropriate return value. In some other modes, it will return the default value. It's entirely up to the mocking framework. It just sees two get(...) calls followed by a thenReturn() call.
Jon Skeet
@Tom: You need code generation to mock classes, but not all mocking frameworks even *allow* that, at least out of the box. If you're only mocking interfaces, Proxy is fine. I can't remember the last time I mocked a class :)
Jon Skeet
+1  A: 

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).

Antonio