Подтвердить что ты не робот

Как проверить несколько вызовов методов с разными параметрами

У меня есть следующий метод, который я хочу проверить на

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 для проверки обоих значений?

4b9b3361

Ответ 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));