Как проверить несколько вызовов методов с разными параметрами
У меня есть следующий метод, который я хочу проверить на
public void methodToTest( Exception e, ActionErrors errors ) {
...
errors.add( "exception.message",
ActionMessageFactory.createErrorMessage(e.toString() ));
errors.add( "exception.detail",
ActionMessageFactory.createErrorMessage(e.getStackTrace()[0].toString() ));
...
}
В моем классе @Test я надеялся сделать что-то подобное, чтобы проверить, что errors.add()
вызывается с "exception.message" и снова с "exception.detail"
verify(errors).add(eq("exception.message"), any(ActionError.class));
verify(errors).add(eq("exception.detail"), any(ActionError.class));
однако Mockito жалуется следующим образом
Argument(s) are different! Wanted:
actionErrors.add(
"exception.message",
<any>
);
Actual invocation has different arguments:
actionErrors.add(
"exception.detail",
[email protected]
);
Как я могу сказать Mockito для проверки обоих значений?
Ответы
Ответ 1
Дальнейшее чтение побудило меня попробовать использовать ArgumentCaptors и следующие работы, хотя и гораздо более подробные, чем хотелось бы.
ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
verify(errors, atLeastOnce()).add(argument.capture(), any(ActionMessage.class));
List<String> values = argument.getAllValues();
assertTrue(values.contains("exception.message"));
assertTrue(values.contains("exception.detail"));
Ответ 2
Если порядок вызовов add()
имеет значение, вы можете использовать InOrder
:
InOrder inOrder = inOrder(errors, errors);
inOrder.verify(errors).add(eq("exception.message"), any(ActionError.class));
inOrder.verify(errors).add(eq("exception.detail"), any(ActionError.class));
Ответ 3
Попробуйте что-то вроде этого:
verify(errors, times(2))
.add(AdditionalMatchers.or(eq("exception.message"), eq("exception.detail")),
any(ActionError.class));
Ответ 4
у вас, вероятно, есть проблемы с кодом. Потому что на самом деле вы на самом деле пишете этот код:
Map<Character, String> map = mock(Map.class);
map.put('a', "a");
map.put('b', "b");
map.put('c', "c");
verify(map).put(eq('c'), anyString());
verify(map).put(eq('a'), anyString());
verify(map).put(eq('b'), anyString());
Обратите внимание, что первое подтверждение не выполняется даже в отношении фактических вызовов.
Кроме того, я бы рекомендовал вам фактически не издеваться над типами, которыми вы не владеете, например, тип расположений.
[EDIT @Brad]
После запуска кода Brice (выше) в моей среде IDE я вижу, что я использовал ActionError вместо ActionMessage, поэтому моя проверка() не была сопоставлена. Сообщение об ошибке, которое я изначально опубликовал, вводило меня в заблуждение, считая, что это был первый аргумент, который не соответствовал. Оказывается, это был второй аргумент.
Итак, ответ на мой вопрос:
/**
* note that ActionMessageFactory.createErrorMessage() returns ActionMessage
* and ActionError extends ActionMessage
*/
verify(errors).add(eq("exception.message"), any(ActionMessage.class));
verify(errors).add(eq("exception.detail"), any(ActionMessage.class));
Ответ 5
Вы можете использовать Mockito.atLeastOnce()
, который позволяет Mockito передавать тест, даже если этот mockObject будет вызываться много раз.
Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(1));
Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(2));