mockito зворотних викликів та отримання значень аргументів


88

Мені не пощастило змусити 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 або передати все, що трапилось, у функцію.


Я не впевнений, що точно розумію, що для вас не вдається. Ваш дзвінок Mockito.when(reader.document(666)).thenReturn(document(fakeIndex(666))повинен налаштувати для вас макетний об’єкт. Що відбувається, коли ви телефонуєте reader.document(666)?
сильно кофеїн

666 працює нормально. Однак я хотів би мати можливість передати певне число X і отримати результат fakeIndex (X). У мене є велика кількість потенційних документів для тестування запитів, і я не хочу вводити їх усі.
nflacco

Відповіді:


103

Я ніколи не використовував 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]));
     }
 });

2
Я щойно помітив посилання з правого боку на Mockito: Як змусити метод повернути аргумент, який йому передано . Схоже, я поруч, якщо не помітити.
Ed Staub

сильна репутація користувача (666) до оригінального співвідношення питань! Це спрацювало дуже добре. Тільки зміна, яку я вніс, щоб отримати компіляцію матеріалів, було відкрито перед Відповіддю Об’єкта (виклик InvocationOnMock) ....
nflacco

54

Перевірте 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());
    }
  });

3
Нічого собі, я не знав, що ти можеш використовувати ArgumentCaptors для заколювання. У цьому посиланні є велике попередження про це. Поступайте обережно.
невинний

3
Так, ти маєш рацію. Викрадачі повинні використовуватися лише з верифікаціями.
кваліфікаційний

41

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

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

Значення аргументу, очевидно, доступне через argument.getValue () для подальших маніпуляцій / перевірки або того, що ви хочете зробити.


2
найкраща відповідь: прямо вперед, легко зрозуміти
Раду Кугут

Не відповідає на запитання. Питання про Mockito.when і не перевіряється.
seBaka28

@ seBaka28 найкращим рішенням для отримання аргументів є викрадач аргументів. Автори Mockito настійно рекомендують використовувати ArgumentCaptors для перевірки, тому я хотів дати повну перспективну відповідь. якщо ви самі вирішили не використовувати їх, це ваш вибір, але не радимо. EDIT: Я не бачу, як це виправдовує голосування проти, але це також ваш вибір.
fl0w

1
Тому що це не відповідає на питання. Так, ArgumentCaptor чудово підходить для захоплення аргументу, але ви не можете використовувати його у поєднанні з when (...). ThenReturn (), що і намагається зробити OP: На основі певного параметра, знущається служба повинен повертати певний об'єкт.
seBaka28,

1
@YuraHoy - це стандартне повідомлення про помилку, коли ви використовуєте перевірку, і об'єкт або метод викликається частіше, ніж ви сказали, що слід очікувати. Ви можете змінити кількість очікувань, додавши аргумент times (n) наступним чином: verify (reader, times (5)) - це передбачає 5 взаємодій. Для довідки дивіться: baeldung.com/mockito-verify
fl0w

13

З Java 8 це може бути приблизно так:

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

Я припускаю, що documentце карта.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.