Как работает «статическое отражение» в Java? (напр. в mockito или easymock) - PullRequest
5 голосов
/ 09 марта 2009

Я парень .NET и в основном пишу на C #.

Начиная с C # 3.0, мы можем использовать лямбда-выражения и деревья выражений для использования статического отражения . Например, можно реализовать 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, переданным как параметр , а не как значение?

Ответы [ 4 ]

5 голосов
/ 09 марта 2009

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

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

4 голосов
/ 09 марта 2009

Библиотеки Java-макетов обычно работают так:

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

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

2 голосов
/ 09 марта 2009

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

1 голос
/ 09 марта 2009

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

...