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


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 답변을 사용하십시오. 변환 List에 Set입력의 설정이 인수 캡처에 의해 주어진 세트와 동일한 것을하고 주장한다.
— 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.