다른 매개 변수로 여러 메서드 호출을 확인하는 방법


116

다음과 같은 방법으로 동작을 확인하고 싶습니다.

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",
    org.apache.struts.action.ActionError@38063806
);

Mockito에게 두 값을 모두 확인하도록하려면 어떻게해야합니까?


1
서명이 다른 두 가지 메서드가 있으면 둘 다에 대해 별도의 테스트 케이스를 작성할 수 있습니다.
Naveen Babu 2011

8
예,하지만이 경우 메서드 서명은 같지만 인수 값만 다릅니다
Brad

당신은 사용해 볼 수 있습니다Mockito.reset()
takacsot

답변:


102

추가 읽기를 통해 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"));

이 접근 방식을 사용하여 특정 매개 변수가 쌍을 이루는 지 확인하는 방법이 있습니까? 말은 예를 들어, 영업 이익의 방법은 두 개의 인수를했고 그들이 함께 불렸다 확인하고 싶어
committedandroider

1
OP의 테스트 케이스는 methodToTest()정확히 한 번만 호출 되므로이 답변은 두 호출이 함께 이루어 졌는지 확인합니다. List<String> values주장되는 캡처 된 값은 테스트중인 두 값만 포함하고 다른 값은 포함하지 않습니다. 당신은 또한 추가 할 수 있습니다 assertTrue(values.size == 2). 이것이 당신이 원하는 것이라면 3 개의 assertTrue 문을 하나의 Hamcrest로 대체 할 것입니다 .assertThat(values, contains("exception.message", "exception.detail"));
Brad

OP의 테스트 케이스가 methodToTest ()를 두 번 호출하지 않습니까?
committedandroider

명확하지 않아서 죄송합니다. OP가 두 개의 인수가 함께 호출되었는지 테스트하려는 시나리오를 언급했습니다. 따라서 메서드 서명은 public void methodToTest (Exception e, Message m, ActionErrors errors) {와 유사하므로 특정 예외가 특정 메시지와 함께 호출됩니다. 나는 당신이 두 ArgumentCaptors이 다음 인덱스를 검색하고 두 값 목록에 그 인덱스의 값을 사용하여 비교할 수 있다는 가정
committedandroider

OP의 테스트 케이스가 methodToTest()한 번 호출 됩니다. 메서드 인수 ActionErrors errors가 내부적으로 두 번 호출됩니다.
Brad

61

add()호출 의 순서 가 관련이있는 경우 다음을 사용할 수 있습니다 InOrder.

InOrder inOrder = inOrder(errors);
inOrder.verify(errors).add(eq("exception.message"), any(ActionError.class));
inOrder.verify(errors).add(eq("exception.detail"), any(ActionError.class));

7
단일 errors인수 를 전달하는 것으로 충분합니다 : InOrder inOrder = inOrder(errors);( 문서 참조 )
GreenhouseVeg

2
주문이 관련이 없으면 어떻게합니까? 종종 그렇습니다.
haelix

1
@haelix이 경우 Brads 답변을 사용하십시오. 변환 ListSet입력의 설정이 인수 캡처에 의해 주어진 세트와 동일한 것을하고 주장한다.
flopshot

25

다음과 같이 시도하십시오.

verify(errors, times(2))
     .add(AdditionalMatchers.or(eq("exception.message"), eq("exception.detail")),
          any(ActionError.class));

5
수표가 너무 느슨합니다.
haelix

17

코드에 문제가있을 수 있습니다. 사실이 코드를 실제로 작성하기 때문입니다.

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());

첫 번째 확인은 실제 호출과 관련하여 순서가 동일하지 않습니다.

또한 소유하지 않은 유형, 예를 들어 struts 유형을 실제로 조롱하지 않는 것이 좋습니다.

[@Brad 수정]

IDE에서 Brice의 코드 (위)를 실행 한 후 ActionMessage 대신 ActionError를 사용했음을 알 수 있으므로 verify ()가 일치하지 않습니다. 처음에 게시 한 오류 메시지는 일치하지 않는 첫 번째 인수라고 오해하게 만들었습니다. 그것은 두 번째 주장이었습니다.

그래서 제 질문에 대한 대답은

/** 
 * 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));

1
당신이 말하려는 것을 이해하지 마십시오. 확인 순서가 중요합니까? 확인 순서가 중요한 경우. 그렇다면 여기에 InOrder API가 제공되는 이유는 무엇입니까?
Oleksandr Papchenko 2016

위에 쓰여진 것과 같이 검증 순서는 무관합니다. 그래서 InOrder.
Brice 2016

12

Mockito.atLeastOnce()mockObject가 여러 번 호출 되더라도 Mockito가 테스트를 통과하도록 허용 하는 것을 사용할 수 있습니다 .

Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(1));

Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(2));

1

1) Mokito에게 총 예상 통화량을 알려줍니다.

2) 각 매개 변수 조합이 예상되는 횟수를 Mokito에게 알립니다.

verify(errors, times(2)).add(any(), any(ActionMessage.class));

verify(errors, atLeastOnce()).add(eq("exception.message"), any());
verify(errors, atLeastOnce()).add(eq("exception.detail"), any());

0

@ sendon1928과 비슷한 방식으로 다음을 사용할 수 있습니다.

Mockito.times(wantedInvocationCount)

메서드가 정확한 횟수로 호출되었는지 확인하기 위해 (내 의견으로는 선호하는 솔루션). 나중에 전화 할 수 있습니다.

Mockito.verifyNoMoreInteractions(mock)

모의가 어떤 맥락에서 더 이상 사용되지 않았는지 확인합니다. 전체 예 :

Mockito.verify(mockObject, Mockito.times(wantedInvocationCount)).testMethod(Mockito.eq(1));

Mockito.verify(mockObject, Mockito.times(wantedInvocationCount)).testMethod(Mockito.eq(2));

Mockito.verifyNoMoreInteractions(mockObject)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.