2009-03-09 13 views
5

Я парень .NET. И я в основном код на C#.Как работает «статическое отражение» в java? (например, в mockito или easymock)

С C# 3.0 мы можем использовать лямбда-выражения и деревья выражений для использования static reflection. Например, можно реализовать GetMethodName в следующем фрагменте кода, чтобы вернуть имя метода передается в параметре:

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

Теперь, когда я смотрю на образцы Mockito (или те, EasyMock) в Java мире, я см:

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

Как это работает?

Как работает метод when? Как он интерпретирует mockedList.get(0) как вызов метода get с 0 передается как параметр, а не как значение?

ответ

5

Откалывающие библиотеки обычно не работают с деревьями выражений. Они создают тип, который реализует соответствующий интерфейс и отвечает на вызовы методов либо путем их записи, либо проверки их и возврата запрограммированных ответов. Обычно это делается либо с прокси (например, RealProxy в .NET, Proxy в Java), либо с динамическим генерированием кода.

В случае EasyMock он использует Proxy (для интерфейсов, в любом случае), как вы можете видеть в исходном коде: посмотрите на org.easymock.internal.JavaProxyFactory.

+0

Прокси-сервер работает с интерфейсами. Настоящие насмешливые рамки для собственного генерации кода. –

+0

В .NET строго типизированные mocking frameworks используют деревья выражений (см. Moq & Rhino mocks) и действительно динамические прокси. Но здесь мне все еще не ясно, как (даже с прокси-серверами) можно смело настроить макет. Что делать, если я набираю «когда (mockedList.get (0) + mockedList.get (2)). ThenReturn (42)»? –

+0

Rhino Mocks существовал задолго до того, как деревья выражений. В некоторых случаях он может использовать деревья выражений * сейчас *, но он не всегда * делает это. (Он все еще работает в .NET 2.0.) Если вы делаете еще один вызов макета, прежде чем указывать результат последнего, результаты зависят от режима макета. –

2

Я никогда не работал с mockito или easymock, но я не думаю, что вызов делает то, что вы думаете. Он не интерпретирует mockedList.get(0) любым специальным способом. Метод get выполнен на объекте mockedList, и результат, который передается в when.

1

mockedList.get(0) - это синтаксис вызова метода и делает именно это. То, что делает этот метод, не совсем ясно. mockedList - это класс подкласса LinkedList, возвращаемый методом mock, который может быть реализован, как только фальшивая инфраструктура сочтет нужным.

4

Java макет библиотеки обычно работают следующим образом:

При создании издеваться, фактический прокси создается (будь то из интерфейса или суб-класса), экземпляр находится в «режиме записи». Это означает, что записывается любой последующий вызов (имя метода, параметры, ожидаемое возвращение). Обратите внимание, что прокси-сервер в режиме записи фактически ничего не записывает. В этом нет никакого отражения. Нет обнаружения метаданных и т. Д. Конечно, эти библиотеки делают некоторые трюки (например, хранят вызовы в локальной локальной переменной для обработки методов, возвращающих пустоту), но идея остается прежней.

Затем, когда запускается «режим воспроизведения», экземпляр mock просто проверяет ожидания из списка вызовов (параметры метода + параметры &).