Mockito 매처 는 정적 메서드 및 해당 메서드 에 대한 호출로 when
, 및을 호출하는 동안 인수 를 나타 verify
냅니다.
Hamcrest 매처 (아카이브 버전) (또는 Hamcrest 스타일 매처)는 객체가 Matcher의 기준과 일치하는 경우 true를 반환 Matcher<T>
하는 메서드 matches(T)
를 구현 하고 노출하는 상태 비 저장 범용 객체 인스턴스입니다 . 그들은 부작용이 없도록 의도되었으며 일반적으로 아래와 같은 주장에 사용됩니다.
/* Mockito */ verify(foo).setPowerLevel(gt(9000));
/* Hamcrest */ assertThat(foo.getPowerLevel(), is(greaterThan(9000)));
Mockito 매처는 Hamcrest 스타일 매처와 별도로 존재 하므로 일치하는 표현식에 대한 설명이 메서드 호출에 직접 들어 맞습니다 . Mockito 매처 T
는 Hamcrest 매처 메서드가 Matcher 객체 (유형 Matcher<T>
)를 반환하는 위치를 반환합니다 .
Mockito 매처 (matcher)는 같은 정적 인 방법을 통해 호출 eq
, any
, gt
,과 startsWith
에 org.mockito.Matchers
와 org.mockito.AdditionalMatchers
. Mockito 버전에서 변경된 어댑터도 있습니다.
- Mockito 1.x의 경우
Matchers
일부 호출 (예 : intThat
또는 argThat
)은 Hamcrest 매처를 매개 변수로 직접 허용하는 Mockito 매처입니다. ArgumentMatcher<T>
extended org.hamcrest.Matcher<T>
는 내부 Hamcrest 표현에 사용되었으며 모든 종류의 Mockito 매처 대신 Hamcrest 매처 기본 클래스 였습니다.
- Mockito 2.0+의 경우 Mockito는 더 이상 Hamcrest에 직접 의존하지 않습니다. 더 이상 구현 되지 않지만 비슷한 방식으로 사용되는 객체
Matchers
로 표현 intThat
되거나 argThat
래핑 된 호출 . 같은 Hamcrest 어댑터 와는 여전히 사용할 수 있지만 이동 한 대신.ArgumentMatcher<T>
org.hamcrest.Matcher<T>
argThat
intThat
MockitoHamcrest
매 처가 Hamcrest이든 단순히 Hamcrest 스타일이든 상관없이 다음과 같이 적용 할 수 있습니다.
/* Mockito matcher intThat adapting Hamcrest-style matcher is(greaterThan(...)) */
verify(foo).setPowerLevel(intThat(is(greaterThan(9000))));
위의 문장에서 : foo.setPowerLevel
는 int
. 인수 로 작동하지 않는를 is(greaterThan(9000))
반환합니다 . Mockito 매처는 Hamcrest 스타일 Matcher를 반환는 것을 랩 그렇게 할 수 있습니다 인수로 표시; Mockito 매처 는 예제 코드의 첫 번째 줄 에서처럼 전체 표현식을 단일 호출로 래핑합니다.Matcher<Integer>
setPowerLevel
intThat
int
gt(9000)
매 처가하는 일 / 반환
when(foo.quux(3, 5)).thenReturn(true);
인수 매처를 사용하지 않을 때 Mockito는 인수 값을 기록하고 equals
메서드 와 비교합니다 .
when(foo.quux(eq(3), eq(5))).thenReturn(true); // same as above
when(foo.quux(anyInt(), gt(5))).thenReturn(true); // this one's different
any
또는 gt
(보다 큼) 과 같은 매처를 호출 하면 Mockito는 Mockito가 해당 동등성 검사를 건너 뛰고 선택한 일치 항목을 적용하도록하는 매처 객체를 저장합니다. 이 경우 argumentCaptor.capture()
나중에 검사를 위해 인수를 저장하는 매처를 저장합니다.
정합 기 반환 더미 값 과 같은 제로로, 빈 컬렉션을, 또는 null
. Mockito는 0과 같은 안전하고 적절한 더미 값을 반환하려고 anyInt()
하거나 any(Integer.class)
또는 빈 List<String>
에 대한 anyListOf(String.class)
. 그러나 유형 삭제로 인해 Mockito에는 또는 null
for 이외의 값을 반환하는 유형 정보가 없으므로 기본 값 을 "자동 해제"하려고하면 NullPointerException이 발생할 수 있습니다 .any()
argThat(...)
null
매처 는 매개 변수 값을 좋아 eq
하고 gt
받습니다. 이상적으로 이러한 값은 스터 빙 / 검증이 시작되기 전에 계산되어야합니다. 다른 호출을 조롱하는 중에 모의를 호출하면 스터 빙을 방해 할 수 있습니다.
Matcher 메서드는 반환 값으로 사용할 수 없습니다. 예를 들어, 문구 thenReturn(anyInt())
나 thenReturn(any(Foo.class))
Mockito 에는 방법이 없습니다 . Mockito는 스터 빙 호출에서 반환 할 인스턴스를 정확히 알아야하며 임의의 반환 값을 선택하지 않습니다.
구현 세부 정보
매처는 ArgumentMatcherStorage 라는 클래스에 포함 된 스택에 (Hamcrest 스타일의 객체 매 처로) 저장됩니다 . MockitoCore 및 Matchers는 각각 ThreadSafeMockingProgress 인스턴스를 소유하며 , 여기 에는 MockingProgress 인스턴스를 보유하는 ThreadLocal 이 정적으로 포함됩니다. 구체적인 ArgumentMatcherStorageImpl 을 보유하는 것은 이 MockingProgressImpl 입니다 . 결과적으로 mock 및 matcher 상태는 정적이지만 Mockito 및 Matchers 클래스간에 일관되게 스레드 범위가 지정됩니다.
대부분의 매처 호출은이 스택에만 추가 and
되지만 or
, 및not
같은 매처는 예외입니다 . 이것은 메소드를 호출하기 전에 왼쪽에서 오른쪽으로 인수를 평가하는 Java 평가 순서 와 완벽하게 일치하며 이에 의존합니다 .
when(foo.quux(anyInt(), and(gt(10), lt(20)))).thenReturn(true);
[6] [5] [1] [4] [2] [3]
이것은 :
anyInt()
스택에 추가하십시오 .
gt(10)
스택에 추가하십시오 .
lt(20)
스택에 추가하십시오 .
- 제거
gt(10)
및 lt(20)
추가합니다 and(gt(10), lt(20))
.
- 를 호출합니다
foo.quux(0, 0)
(스텁 처리되지 않은 경우) false
. 기본값을 반환합니다 . 내부적으로 Mockito quux(int, int)
는 가장 최근 통화로 표시합니다 .
when(false)
인수를 버리고 quux(int, int)
5에서 식별 된 메서드를 스텁 할 준비를하는를 호출 합니다. 유효한 상태는 스택 길이가 0 (동일) 또는 2 (매처)이며 스택에 두 개의 일치자가 있습니다 (1 단계 및 4 단계). Mockito any()
는 첫 번째 인수와 and(gt(10), lt(20))
두 번째 인수에 대해 매처를 사용 하여 메서드를 스텁 하고 스택을 지 웁니다.
이것은 몇 가지 규칙을 보여줍니다.
Mockito는 quux(anyInt(), 0)
과 의 차이를 알 수 없습니다 quux(0, anyInt())
. 둘 다 quux(0, 0)
스택에 하나의 int 매 처가 있는 호출처럼 보입니다 . 따라서 하나의 매처를 사용하는 경우 모든 인수를 일치시켜야합니다.
통화 순서는 중요 할뿐만 아니라이 모든 것이 작동하도록 합니다. 매처를 변수로 추출하는 것은 일반적으로 호출 순서를 변경하기 때문에 일반적으로 작동하지 않습니다. 그러나 매처를 메서드로 추출하는 것은 훌륭하게 작동합니다.
int between10And20 = and(gt(10), lt(20));
/* BAD */ when(foo.quux(anyInt(), between10And20)).thenReturn(true);
// Mockito sees the stack as the opposite: and(gt(10), lt(20)), anyInt().
public static int anyIntBetween10And20() { return and(gt(10), lt(20)); }
/* OK */ when(foo.quux(anyInt(), anyIntBetween10And20())).thenReturn(true);
// The helper method calls the matcher methods in the right order.
스택은 Mockito가 매우 신중하게 감시 할 수 없을 정도로 자주 변경됩니다. Mockito 또는 mock과 상호 작용할 때만 스택을 확인할 수 있으며, 매 처가 즉시 사용되는지 또는 실수로 버려지는지 알지 못한 채 매처를 수락해야합니다. 이론적으로 스택은 when
또는 호출 외부에서 항상 비어 있어야 verify
하지만 Mockito는이를 자동으로 확인할 수 없습니다. 를 사용하여 수동으로 확인할 수 있습니다 Mockito.validateMockitoUsage()
.
를 호출 할 when
때 Mockito는 실제로 해당 메서드를 호출합니다.이 메서드는 예외를 throw하기 위해 메서드를 스텁 처리 한 경우 (또는 0이 아니거나 null이 아닌 값이 필요한 경우) 예외를 throw합니다.
doReturn
그리고 doAnswer
(등) 실제 메소드를 호출 하지 않으며 종종 유용한 대안입니다.
eq
스터 빙 도중에 모의 메서드를 호출했다면 (예 : matcher에 대한 답변을 계산하기 위해 ) Mockito는 대신 해당 호출 에 대해 스택 길이를 확인하고 실패 할 가능성이 높습니다.
최종 메서드 스터 빙 / 검증 과 같이 나쁜 일을하려고하면 Mockito는 실제 메서드를 호출하고 추가 매처를 스택에 남겨 둡니다 . final
메서드 호출 예외가 발생하지 않을 수 있습니다,하지만 당신은 얻을 수 InvalidUseOfMatchersException을 모의와 부유 매처 (matcher) 당신 옆의 상호 작용에서.
일반적인 문제
InvalidUseOfMatchersException :
매처를 전혀 사용하지 않는 경우 모든 단일 인수에 정확히 하나의 매처 호출이 있는지 확인하고 when
또는 verify
호출 외부에서 매처를 사용하지 않았는지 확인 합니다. 매처는 스텁 반환 값 또는 필드 / 변수로 사용해서는 안됩니다.
matcher 인수 제공의 일부로 mock을 호출하지 않았는지 확인하십시오.
매처를 사용하여 최종 메서드를 스텁 / 검증하려고하지 않는지 확인하십시오. 스택에 매처를 남겨 두는 좋은 방법이며, 최종 메서드가 예외를 throw하지 않는 한, 조롱하는 메서드가 최종임을 깨달은 유일한 시간 일 수 있습니다.
기본 인수가있는 NullPointerException : 0 (Integer) any()
을 any(Integer.class)
반환 하는 동안 null을 반환합니다. 이것은 Integer 대신 NullPointerException
an int
을 기대하는 경우 발생할 수 있습니다 . 어쨌든 anyInt()
0을 반환하고 자동 박싱 단계를 건너 뛰는을 선호 합니다.
NullPointerException 또는 기타 예외 :에 대한 호출 when(foo.bar(any())).thenReturn(baz)
은 실제로를 호출합니다 foo.bar(null)
. 이는 null 인수를받을 때 예외를 throw하기 위해 스텁 처리되었을 수 있습니다. 로 전환 doReturn(baz).when(foo).bar(any())
하면 스텁 동작 을 건너 뜁니다 .
일반적인 문제 해결
사용 MockitoJUnitRunner는 , 또는 명시 적으로 호출 validateMockitoUsage
하여에서 tearDown
또는 @After
(주자가 자동으로 당신을 위해 할 것이다)하는 방법. 이것은 매처를 오용했는지 여부를 확인하는 데 도움이됩니다.
디버깅을 위해 validateMockitoUsage
코드에 직접 호출을 추가 하십시오. 스택에 무언가가 있으면 던질 것이며 이는 나쁜 증상에 대한 좋은 경고입니다.