Mockito.any() передает интерфейс с дженериками

#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 объект, соответствующий типу, и интерфейс предоставляет это, я думаю, вы могли бы проверить это в пользовательском сопоставителе. Или, например, в случае a Collection вы можете проверить тип элементов.

4. Matchers был заменен на ArgumentMatchers в Mockito v2

5. @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 8 any() его можно использовать встроенным без необходимости отдельного назначения.

3. @kevinarpe если у вас есть несколько сопоставителей аргументов, они должны вызываться в порядке, указанном в языке Java.