У меня есть класс, который, по сути, выглядит так:
class Checkpointer {
public <Input,Output> Output runFunction(Input input, Function<Input,Output> function) {
Output output;
// Sometimes run the function, sometimes return an Output from a cache
return output
}
}
Я хотел бы издеваться над этим классом, используя Mockito doAnswer:
Checkpointer checkpointer; // mocked via @Mock annotation
Mockito
.doAnswer(/* ??? */)
.when(checkpointer)
.runFunction(Mockito.any(), Mockito.any());
Функция, которую я хочу имитировать, должна быть универсальной. Можно ли это сделать?
Например, моя первая попытка выдала следующее. Мало того, что я прибегал к Object в качестве аргументов типа для Function, так еще и компилятор был недоволен непроверенным приведением типов:
Mockito.doAnswer((invocation) ->
{
// compiler is not happy with this cast V
Function<Object,Object> function = (Function<Object,Object>)invocation.getArguments()[1];
return function.apply(invocation.getArgument(0));
}).when(checkpointer).runFunction(Mockito.any(), Mockito.any());
Если это невозможно сделать, я думаю, можно попробовать написать свой собственный фиктивный класс, расширяющий первый, и использовать Mockito.spy.




Проблема здесь в том, что вы настаиваете на использовании getArguments, который возвращает Object[]
Так как вы знать индекс аргумента Function, вы можете использовать getArgument(index), так как вы делаете строку после этого.
final Function<String, String> argument = invocation.getArgument(1);
Это то, что вы ищете? Вывод типа для универсального типа getArgument работает нормально.
Если нет, можете ли вы привести более подробный пример?
@GordonBean, что вы имеете в виду под «но не взломом Function<Object,Object>»? Вы можете использовать любые типы, которые вы хотите с этим.
Я хочу сказать, что метод контрольного указателя ожидает аргумент Function<Input,Output>, поэтому тип Function<Object,Object> не является точным на 100%. Таким образом, лямбда doAnswer гарантированно возвращает только Object, даже если метод, который она имитирует, утверждает, что возвращает что-то универсального типа Output.
@GordonBean Дело в том, что когда вы тестируете, вы точно знаете, с какими типами объектов вы будете иметь дело. Так что "общая" проблема имхо не проблема
в рамках данного вызова вызывающей функции метод runFunction будет вызываться несколько раз с разными типами. Поэтому я не могу издеваться над функцией один раз с одним набором аргументов типа. Думаю, я мог бы использовать сопоставители аргументов, чтобы включить тип ввода и настроить doAnswer для каждого ожидаемого типа ввода.
Спасибо за ответ - ваш ответ касается предупреждения компилятора, но не взлома
Function<Object,Object>. Однако, какFunction<Object,Object>работает, я думаю, что ваш ответ дает мне приемлемый ответ.