Mockito: как имитировать doAnswer для универсального метода

У меня есть класс, который, по сути, выглядит так:

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.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
1 930
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема здесь в том, что вы настаиваете на использовании getArguments, который возвращает Object[]
Так как вы знать индекс аргумента Function, вы можете использовать getArgument(index), так как вы делаете строку после этого.

final Function<String, String> argument = invocation.getArgument(1);

Это то, что вы ищете? Вывод типа для универсального типа getArgument работает нормально.

Если нет, можете ли вы привести более подробный пример?

Спасибо за ответ - ваш ответ касается предупреждения компилятора, но не взлома Function<Object,Object>. Однако, как Function<Object,Object>работает, я думаю, что ваш ответ дает мне приемлемый ответ.

Gordon Bean 28.02.2019 21:00

@GordonBean, что вы имеете в виду под «но не взломом Function<Object,Object>»? Вы можете использовать любые типы, которые вы хотите с этим.

LppEdd 28.02.2019 21:15

Я хочу сказать, что метод контрольного указателя ожидает аргумент Function<Input,Output>, поэтому тип Function<Object,Object> не является точным на 100%. Таким образом, лямбда doAnswer гарантированно возвращает только Object, даже если метод, который она имитирует, утверждает, что возвращает что-то универсального типа Output.

Gordon Bean 28.02.2019 22:39

@GordonBean Дело в том, что когда вы тестируете, вы точно знаете, с какими типами объектов вы будете иметь дело. Так что "общая" проблема имхо не проблема

LppEdd 28.02.2019 22:44

в рамках данного вызова вызывающей функции метод runFunction будет вызываться несколько раз с разными типами. Поэтому я не могу издеваться над функцией один раз с одним набором аргументов типа. Думаю, я мог бы использовать сопоставители аргументов, чтобы включить тип ввода и настроить doAnswer для каждого ожидаемого типа ввода.

Gordon Bean 28.02.2019 22:54

Другие вопросы по теме

Ошибка поставщика пользовательских ребер: как написать общий метод?
Как замыкания определяют свой тип на основе типажа, который они должны реализовать?
Проверьте, является ли класс Scala экземпляром T
Почему тип универсальной функции сам по себе не является универсальным?
MappedSuperclass сопоставляет все дочерние объекты с одним дочерним
Pureconfig нет ручного импорта pureconfig.generic.auto._
Как правильно использовать Gson для десериализации объекта универсального типа с помощью статического служебного метода?
Связанный параметр типа не учитывается, когда универсальный тип используется с неограниченным подстановочным знаком
Введите безопасное слияние карты с несколькими типами для ее значения; `несовместимые типы java.lang.Object не могут быть преобразованы в захват № 1 из ?`
Как определить интерфейс или класс с универсальным типом, чей универсальный тип содержит универсальный тип