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.