обратные вызовы mockito и получение значений аргументов

Мне не удалось заставить Mockito захватывать значения аргументов функции! Я издеваюсь над индексом поисковой системы и вместо того, чтобы строить индекс, я просто использую хеш.

// Fake index for solr
Hashmap<Integer,Document> fakeIndex;

// Add a document 666 to the fakeIndex
SolrIndexReader reader = Mockito.mock(SolrIndexReader.class);

// Give the reader access to the fake index
Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666))

Я не могу использовать произвольные аргументы, потому что я проверяю результаты запросов (т.е. какие документы они возвращают). Точно так же я не хочу указывать конкретное значение и иметь строку для каждого документа!

Mockito.when(reader.document(0)).thenReturn(document(fakeIndex(0))
Mockito.when(reader.document(1)).thenReturn(document(fakeIndex(1))
....
Mockito.when(reader.document(n)).thenReturn(document(fakeIndex(n))

Я просмотрел раздел обратных вызовов на странице Использование Mockito. К сожалению, это не Java, и я не мог получить собственную интерпретацию этого для работы на Java.

РЕДАКТИРОВАТЬ (для пояснения): Как заставить Mockito захватить аргумент X и передать его в мою функцию? Я хочу, чтобы в функцию было передано точное значение (или ссылку) X.

Я не хочу перечислять все случаи, и произвольный аргумент не сработает, потому что я проверяю разные результаты для разных запросов.

На странице Mockito говорится

val mockedList = mock[List[String]]
mockedList.get(anyInt) answers { i => "The parameter is " + i.toString } 

Это не java, и я не знаю, как перевести на java или передать то, что произошло, в функцию.


person nflacco    schedule 08.07.2011    source источник
comment
Я не уверен, что понимаю, что именно у вас не получается. Ваш звонок в Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666)) должен настроить для вас фиктивный объект. Что происходит, когда вы звоните reader.document(666)?   -  person highlycaffeinated    schedule 09.07.2011
comment
666 работает нормально. Однако я хотел бы иметь возможность передать конкретное число X и получить результат fakeIndex (X). У меня есть большое количество потенциальных документов для проверки запросов, и я не хочу вводить их все.   -  person nflacco    schedule 09.07.2011


Ответы (4)


Я никогда не использовал Mockito, но хочу научиться, так что начнем. Если ответит кто-то менее невежественный, чем я, сначала попробуйте его ответ!

Mockito.when(reader.document(anyInt())).thenAnswer(new Answer() {
 public Object answer(InvocationOnMock invocation) {
     Object[] args = invocation.getArguments();
     Object mock = invocation.getMock();
     return document(fakeIndex((int)(Integer)args[0]));
     }
 });
person Ed Staub    schedule 09.07.2011
comment
Я только что заметил ссылку справа на Mockito: как заставить метод возвращать переданный ему аргумент. Похоже, я близок, если не на месте. - person Ed Staub; 09.07.2011
comment
сильная репутация пользователя (666) с исходным соотношением вопросов! Это сработало очень хорошо. Только изменение, которое я сделал для компиляции материала, было опубликовано перед ответом объекта (вызов InvocationOnMock) .... - person nflacco; 09.07.2011

Ознакомьтесь с ArgumentCaptors:

https://site.mockito.org/javadoc/current/org/mockito/ArgumentCaptor.html

ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
Mockito.when(reader.document(argument.capture())).thenAnswer(
  new Answer() {
    Object answer(InvocationOnMock invocation) {
      return document(argument.getValue());
    }
  });
person qualidafial    schedule 16.07.2011
comment
Вау, я не знал, что вы можете использовать ArgumentCaptors для заглушки. Однако в этой ссылке есть большое предупреждение об этом. Действовать с осторожностью. - person einnocent; 16.12.2015
comment
Ага, ты прав. Захватчики следует использовать только при проверках. - person qualidafial; 16.02.2016

Возможно, вы захотите использовать verify () в сочетании с ArgumentCaptor, чтобы гарантировать выполнение в тесте, и ArgumentCaptor для оценки аргументов:

ArgumentCaptor<Document> argument = ArgumentCaptor.forClass(Document.class);
verify(reader).document(argument.capture());
assertEquals(*expected value here*, argument.getValue());

Очевидно, что значение аргумента доступно через arguments.getValue () для дальнейших манипуляций / проверки или того, что вы хотите сделать.

person fl0w    schedule 28.10.2016
comment
лучший ответ: прямо, легко понять - person Radu Cugut; 20.09.2019
comment
Не отвечает на вопрос. Вопрос по поводу Mockito.when и не проверять. - person seBaka28; 07.09.2020
comment
@ seBaka28 лучшее решение для получения аргументов - это захват аргументов. Авторы Mockito настоятельно рекомендуют использовать ArgumentCaptors вместе с verify, поэтому я хотел дать полный перспективный ответ. если вы сами решите не использовать их, это ваш выбор, но не рекомендуется. РЕДАКТИРОВАТЬ: Я не понимаю, как это оправдывает отрицательный голос, но это также ваш выбор. - person fl0w; 07.09.2020
comment
Потому что это не отвечает на вопрос. Да, ArgumentCaptor отлично подходит, когда вы хотите захватить аргумент, но вы не можете использовать его вместе с when (...). ThenReturn (), что пытается сделать OP: на основе определенного параметра, имитируемая служба должен возвращать определенный объект. - person seBaka28; 09.09.2020
comment
Именно это здесь и требуется. вы можете сделать это с помощью захватчиков аргументов. Пожалуйста, попробуйте сами. - person fl0w; 11.09.2020
comment
Что делать, если метод mock вызывается несколько раз? Я получаю исключение TooManyActualInvocations и не знаю, что с этим делать. Мне нужен последний результат вызова - person YuraHoy; 14.09.2020
comment
@YuraHoy, это стандартное сообщение об ошибке, когда вы используете verify, и объект или метод вызывается чаще, чем вы сказали, что verify ожидать. Вы можете изменить счетчик ожидания, добавив аргумент times (n) следующим образом: verify (reader, times (5)) - это ожидает 5 взаимодействий. Для справки см: baeldung.com/mockito-verify - person fl0w; 15.09.2020
comment
и все значения нескольких вызовов доступны в вашем captor captor.getAllValues ​​() - person fl0w; 15.09.2020

В Java 8 это могло быть примерно так:

Mockito.when(reader.document(anyInt())).thenAnswer(
  (InvocationOnMock invocation) -> document(invocation.getArguments()[0]));

Я предполагаю, что document - это карта.

person Jean-François Beauchef    schedule 15.10.2016