#java #generics #mockito
#java #обобщения #mockito
Вопрос:
возможно ли передать тип интерфейса с дженериками?
Интерфейс:
public interface AsyncCallback<T>
В моем методе тестирования:
Mockito.any(AsyncCallback.class)
Установка <ResponseX>
behind или for .class
не сработала.
Ответ №1:
Существует типобезопасный способ: используйте ArgumentMatchers.any()
и уточняйте его с помощью типа:
ArgumentMatchers.<AsyncCallback<ResponseX>>any()
Комментарии:
1. Я подтверждаю, что этот ответ работает и правильно подавляет предупреждение.
2. На самом деле это не безопаснее, поскольку фактический метод в любом случае может быть вызван только с правильно введенным аргументом. Просто было необходимо удовлетворить компилятор до java8, в котором отсутствовал такой тип вывода.
3. С новыми версиями Mockito:
(Matchers.<AsyncCallback<ResponseX>>any()
4.
Matchers
на самом деле устарел, ноArgumentMatchers
работал.5.
ArgumentMatchers.<List<S8Z2DETNSGDto>>any()
— IDE намекает мне, что могут быть выведены явные аргументы типа. Это означает, что нет необходимости явно определять типы иArgumentMatchers.any()
будет иметь тот же результат
Ответ №2:
Используя Java 8, вы можете просто использовать any()
(предполагая статический импорт) без аргумента или параметра типа из-за расширенного вывода типа. Теперь компилятор знает из целевого типа (типа аргумента метода), который вы на самом деле имеете в виду Matchers.<AsyncCallback<ResponseX>>any()
, что является решением до Java 8.
Комментарии:
1. Не
any()
AsyncCallback<AnyOtherType>
будет совпадать?2. Меня интересует ситуация, когда тип аргумента также является общим, но вы хотите издеваться над ним только для одного конкретного типа (или издеваться над ним для нескольких типов по-разному). Приведено
when(x.y(any())).thenAnswer(...)
, например, гдеy
находитсяpublic <T> T y(AsyncCallback<T> arg)
. Возможно, было бы лучше проверить тип в ответе, если это то, что нужно?3. @MatthewRead Из-за удаления фактический тип не может быть проверен во время выполнения с помощью Mockito. Так что вы даже не можете использовать
isA()
. Если объект содержитClass
объект, соответствующий типу, и интерфейс предоставляет это, я думаю, вы могли бы проверить это в пользовательском сопоставителе. Или, например, в случае aCollection
вы можете проверить тип элементов.4.
Matchers
был заменен наArgumentMatchers
в Mockito v25. @YuraHoy Проверка типов среды выполнения здесь не выполняется даже до версии 8. Тип должен был быть добавлен только для удовлетворения компилятора. Теперь компилятор выводит тип из сигнатуры метода. См . docs.oracle.com/javase/tutorial/java/generics /…
Ответ №3:
Мне пришлось принять следующий механизм, чтобы разрешить дженерики:
import static org.mockito.Matchers.any;
List<String> list = any();
when(callMyMethod.getResult(list)).thenReturn(myResultString);
Надеюсь, это кому-то поможет.
Комментарии:
1. Смотрите мой ответ: в Java 8 в этом больше нет необходимости.
Ответ №4:
Публикация комментария pierrefevrier в качестве ответа, который может быть полезен, если он присутствует в ответе вместо комментариев.
С новыми версиями Mockito: (Matchers.<AsyncCallback<ResponseX>>any()
Комментарии:
1. я добавил его комментарий к исходному ответу
Ответ №5:
В дополнение к ответу thSoft, ввод квалифицированного вызова метода any() в метод означал, что я мог удалить квалификацию, поскольку возвращаемый тип допускал вывод:
private HashMap<String, String> anyStringStringHashMap() {
return Matchers.any();
}
Ответ №6:
У меня была аналогичная проблема с использованием Spring Example
:
Mockito.when(repo.findAll(Mockito.<Example<SrvReqToSupplierComment>>any()))
.thenReturn(Lists.emptyList());
Здесь вы должны использовать квалификацию, метод b / c findAll может принимать несколько типов, таких как Sort
и Iterable
. Вы также можете использовать Mockito.any(Example.class)
, конечно, с предупреждением о безопасности типов.
Комментарии:
1. Это тоже была моя проблема. Обычно я использую статический импорт для org.mockito. Mockito. *, но в этом случае только метод when() может использоваться без квалификации, метод any() нуждается в квалификации.
Ответ №7:
Использование квалифицированного обобщенного типа с методом без аргументов any()
работает (т.Е. ArgumentMatchers.<AsyncCallback<ResponseX>>any()
), Но может стать громоздким для более длинных обобщенных выражений. Альтернативой является помещение any()
вызова без аргументов в свой собственный универсальный метод, используя конкретный универсальный тип в качестве возвращаемого типа:
private static <T> AsyncCallback<T> anyAsyncCallback() {
return ArgumentMatchers.any()
}
Использование
Mockito.verify(mockObject).performCallback(any(), anyAsyncCallback())
Ответ №8:
Вы можете просто использовать его, добавив предупреждения о подавлении, если хотите:
@SuppressWarnings("unchecked")
AsyncCallback<ResponseX> callback = Mockito.any(AsyncCallback.class)
Если бы Java разрешала «общие» дженерики, у них мог бы быть такой метод, который вы ищете
private static <T, E> T<E> mock(Class<T<E>> clazz)
Комментарии:
1. Когда я попробовал это, я получил ошибку в своем тесте:
You cannot use argument matchers outside of verification or stubbing.
2. Не очень хорошая идея использовать
@SuppressWarnings
: до java 8, если вы собирались назначить его отдельной переменной, вы могли бы просто использоватьany()
as в ответе theINtoy. Теперь с java 8any()
его можно использовать встроенным без необходимости отдельного назначения.3. @kevinarpe если у вас есть несколько сопоставителей аргументов, они должны вызываться в порядке, указанном в языке Java.