Как имитировать общий параметр для модульного теста в java?

У меня есть подпись функции, которую я хотел бы высмеять над внешней службой.

public <T> void save(T item, AnotherClass anotherClassObject);

Учитывая эту сигнатуру функции и имя класса IGenericService, как можно было издеваться над ней с помощью PowerMock? Или Мокито?

Для этого универсального я использую: Класс Theodore для T в T item. Например, я пробовал использовать:

doNothing().when(iGenericServiceMock.save(any(Theodore.class),
                    any(AnotherClass.class));

IntelliJ проверяет это:

save(T, AnotherClass) cannot be applied to 
(org.Hamcrest.Matcher<Theodore>, org.Hamcrest.Matcher<AnotherClass>)

Причина здесь следующая:

reason: No instance(s) of type variable T exist 
so that Matcher<T> conforms to AnotherClass

Во-первых, проблема должна быть решена, если аргумент дженериков обрабатывается правильно. Что можно было бы сделать в таких ситуациях?

ОБНОВЛЕНИЕ: Как сообщил ETO:

doNothing().when(mockedObject).methodToMock(argMatcher); 

разделяет ту же судьбу.

Не могли бы вы добавить код, который вы пытаетесь, в блок кода (с отступом 4). Трудно понять, что вы говорите.

Andy Turner 31.10.2018 12:31

А можно ли поменять сигнатуру метода save? T на самом деле не делает здесь ничего полезного; вы можете просто использовать вместо него Object.

Andy Turner 31.10.2018 12:32

@AndyTurner На самом деле интерфейс вполне рабочий. Это интерфейс DynamoDBService. Item представляет объект DAO для имени таблицы в БД.

Rohan Kumar 31.10.2018 13:42

Может быть, это действительно так, просто бессмысленно иметь там переменную типа.

Andy Turner 31.10.2018 13:50

Это кажется бессмысленным вне контекста. Однако его реализация не примет объект, если вы об этом задумаетесь. Например, передавать объект вместо DAOTableName.java непрактично, если учесть, как DynamoDBMapper принимает входные параметры. Generic помогает разрешить таблицу БД из самого имени элемента. Так. Могу ошибаться, не знаю. :П

Rohan Kumar 31.10.2018 14:00
3
5
2 705
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Попробуйте использовать ArgumentMatcher от Mockito. Также в when поместите только ссылку на макет:

doReturn(null).when(iGenericServiceMock).save(
    ArgumentMatchers.<Theodore>any(), ArgumentMatchers.any(AnotherClass.class));

Я попытался увидеть, где реализация этого ответа возьмет код. В моей библиотеке еще нет ArgumentMatchers. У него есть ArgumentMatcher, но я проверил, и они такие разные.

Rohan Kumar 31.10.2018 14:02

В этом случае вам может потребоваться использовать класс Matchers

Maciej Kowalski 31.10.2018 14:11
Ответ принят как подходящий

Вы передаете when неверные параметры. Это может немного сбить с толку, но есть два разных использования метода when (на самом деле это два разных метода):

  1. when(mockedObject.methodYouWantToMock(expectedParameter, orYourMatcher)).thenReturn(objectToReturn);
    
  2. doReturn(objectToReturn).when(mockedObject).methodYouWantToMock(expectedParameter, orYourMatcher);
    

Примечание: обратите внимание на входные параметры метода when в обоих случаях..

В вашем конкретном случае вы можете сделать что-то вроде этого:

doReturn(null).when(iGenericServiceMock).save(any(Theodore.class), any(AnotherClass.class));

Это исправит ваши проблемы с компиляцией. Однако тест завершится неудачно во время выполнения с org.mockito.exceptions.misusing.CannotStubVoidMethodWithReturnValue, потому что вы пытаетесь вернуть что-то из метода void (null - это не void). Что вам следует сделать:

doNothing().when(iGenericServiceMock).save(any(Theodore.class), any(AnotherClass.class));

Позже вы можете проверить взаимодействие с вашим макетом, используя метод verify.

ОБНОВИТЬ:

Проверьте свой импорт. Вы должны использовать org.mockito.Matchers.any вместо org.hamcrest.Matchers.any.

Привет, спасибо, что указали! Я был так сбит с толку, что на самом деле я реализовал doNothing (). When (mockedObject) .methodIWantToMock (anyMatcher, anyMatcher) точно так же, как последний фрагмент кода вашего ответа. Intellij все еще проверяет это. Какие-либо предложения?

Rohan Kumar 31.10.2018 13:48

Тем не менее полезно!

Rohan Kumar 31.10.2018 13:48

Проверьте свой импорт. Вы должны использовать org.mockito.Matchers.any вместо org.hamcrest.Matchers.any.

ETO 31.10.2018 13:53

Отличные и быстрые ответы! Наконец-то мне удалось сгладить это с помощью следующего кода:

doNothing().when(iGenericServiceMock).save(Mockito.any(), Mockito.any()); 

Только когда я добавил Mockito к любому методу, Intellij снова обрадовался этому.

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