Mockito에서 Varargs를 올바르게 일치시키는 방법


152

Mockito를 사용하여 vararg 매개 변수를 사용하여 메서드를 모방하려고했습니다.

interface A {
  B b(int x, int y, C... c);
}

A a = mock(A.class);
B b = mock(B.class);

when(a.b(anyInt(), anyInt(), any(C[].class))).thenReturn(b);
assertEquals(b, a.b(1, 2));

작동하지 않지만 대신 대신하면 :

when(a.b(anyInt(), anyInt())).thenReturn(b);
assertEquals(b, a.b(1, 2));

메서드를 스텁 할 때 varargs 인수를 완전히 생략 했음에도 불구하고 작동합니다.

단서가 있습니까?


마지막 예제가 작동한다는 사실은 varargs 매개 변수가 0이 아닌 경우와 일치하기 때문에 사소한 것입니다.
topchef April

답변:


235

Mockito 1.8.1은 anyVararg () 매처를 도입 했습니다 .

when(a.b(anyInt(), anyInt(), Matchers.<String>anyVararg())).thenReturn(b);

https://code.google.com/archive/p/mockito/issues/62에 대한 기록도 참조하십시오.

더 이상 사용되지 않는 새 구문을 편집하십시오 .

when(a.b(anyInt(), anyInt(), ArgumentMatchers.<String>any())).thenReturn(b);

26
anyVararg()반환 유형으로 Object가 있습니다. 모든 var arg 유형 (예 : String ..., Integer ... 등)과 호환되도록하려면 명시 적 캐스팅을 수행하십시오. 예를 들어, doSomething(Integer number, String ... args)mock / stub 코드를 다음과 같이 할 수 있습니다 when(mock).doSomething(eq(1), (String) anyVarargs()). 컴파일 오류를 처리해야합니다.
Psycho Punch

15
정보를 위해 anyVararg는 더 이상 사용되지 않습니다 : "@deprecated 2.1.0부터 any ()"
alexbt

5
Matchersorg.hamcrest.Matchers클래스와 의 이름 충돌을 피하기 위해 더 이상 사용되지 않으며 mockito v3.0에서 제거 될 것입니다. ArgumentMatchers대신 사용하십시오 .
JonyD

31

다소 문서화되지 않은 기능 : vararg 인수와 일치하는 사용자 정의 Matcher를 개발 org.mockito.internal.matchers.VarargMatcher하려면 올바르게 작동하도록 구현해야 합니다. Mockito가 Matcher를 사용하여 varargs로 메소드를 호출 할 때 인수를 올바르게 비교하지 않는 빈 마커 인터페이스입니다.

예를 들면 다음과 같습니다.

class MyVarargMatcher extends ArgumentMatcher<C[]> implements VarargMatcher {
    @Override public boolean matches(Object varargArgument) {
        return /* does it match? */ true;
    }
}

when(a.b(anyInt(), anyInt(), argThat(new MyVarargMatcher()))).thenReturn(b);

7

여기에 Eli Levine의 대답을 바탕으로보다 일반적인 해결책이 있습니다.

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.mockito.ArgumentMatcher;
import org.mockito.internal.matchers.VarargMatcher;

import static org.mockito.Matchers.argThat;

public class VarArgMatcher<T> extends ArgumentMatcher<T[]> implements VarargMatcher {

    public static <T> T[] varArgThat(Matcher<T[]> hamcrestMatcher) {
        argThat(new VarArgMatcher(hamcrestMatcher));
        return null;
    }

    private final Matcher<T[]> hamcrestMatcher;

    private VarArgMatcher(Matcher<T[]> hamcrestMatcher) {
        this.hamcrestMatcher = hamcrestMatcher;
    }

    @Override
    public boolean matches(Object o) {
        return hamcrestMatcher.matches(o);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("has varargs: ").appendDescriptionOf(hamcrestMatcher);
    }

}

그런 다음 hamcrest의 배열 매처와 함께 사용할 수 있습니다.

verify(a).b(VarArgMatcher.varArgThat(
            org.hamcrest.collection.IsArrayContaining.hasItemInArray("Test")));

(정적으로 임포트하면 이것을 더 읽기 쉽게 만듭니다.)


좋은. 이것은 Mockito IMO에 내장되어야합니다.
bryant

나는 Hamcrest에 대해 이와 같은 것을 추가하기 위해 문제를 제기했습니다. github.com/mockito/mockito/issues/356
Mark

Mockito 1입니까? 2.10에 대해 컴파일하려고 할 때 다양한 컴파일 오류가 발생합니다.
Frans

@Frans이 답변을 쓸 때 2 릴리스가 아직 베타 버전 인 것처럼 보이므로 Mockito v1.10.19 또는 그 주변을 위해 작성되었을 것입니다. ( github.com/mockito/mockito/releases ) 그것은 아마도 업데이트 할 ... - D입니다
피터 웨스트 마 코트

3

Peter Westmacott의 답변에서 코드를 사용했지만 Mockito 2.2.15에서는 다음을 수행 할 수 있습니다.

verify(a).method(100L, arg1, arg2, arg3)

arg1, arg2, arg3varargs는 어디에 있습니까 ?


1

topchef의 답변을 바탕으로

2.0.31-beta의 경우 Matchers.anyVararrg 대신 Mockito.anyVararg를 사용해야했습니다.

when(a.b(anyInt(), anyInt(), Mockito.<String>anyVararg())).thenReturn(b);

3
정보를 위해 anyVararg는 더 이상 사용되지 않습니다 : "@deprecated 2.1.0부터 any ()"
alexbt

0

필자의 경우 인수를 캡처하려는 메소드의 서명은 다음과 같습니다.

    public byte[] write(byte ... data) throws IOException;

이 경우 명시 적으로 바이트 배열로 캐스트해야합니다 .

       when(spi.write((byte[])anyVararg())).thenReturn(someValue);

mockito 버전을 사용하고 있습니다 1.10.19


0

인수를 반복 할 수도 있습니다.

Object[] args = invocation.getArguments(); 
for( int argNo = 0; argNo < args.length; ++argNo) { 
    // ... do something with args[argNo] 
}

예를 들어, 유형을 확인하고 적절하게 캐스팅하고 목록에 추가하십시오.


0

@topchef의 답변을 채택하여

Mockito.when(a.b(Mockito.anyInt(), Mockito.anyInt(), Mockito.any())).thenReturn(b);

Mockito 2.23.4의 Java 문서에 따라 Mockito.any () "널과 varargs를 포함한 모든 항목을 일치시킵니다."


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