이 코드를 고려하십시오.
public class DummyClass {
public List<? extends Number> dummyMethod() {
return new ArrayList<Integer>();
}
}
public class DummyClassTest {
public void testMockitoWithGenerics() {
DummyClass dummyClass = Mockito.mock(DummyClass.class);
List<? extends Number> someList = new ArrayList<Integer>();
Mockito.when(dummyClass.dummyMethod()).thenReturn(someList); //Compiler complains about this
}
}
컴파일러는의 동작을 스텁하려는 행에 대해 불평합니다 dummyMethod()
. 경계가있는 와일드 카드가있는 유형을 반환하는 스텁 메소드에 대한 포인터가 있습니까?
답변
이 목적을 위해 비 유형 안전 메소드 doReturn 을 사용할 수도 있습니다.
@Test
public void testMockitoWithGenerics()
{
DummyClass dummyClass = Mockito.mock(DummyClass.class);
List<? extends Number> someList = new ArrayList<Integer>();
Mockito.doReturn(someList).when(dummyClass).dummyMethod();
Assert.assertEquals(someList, dummyClass.dummyMethod());
}
Mockito의 Google 그룹에서 논의한 대로 .
이보다 간단하지만 thenAnswer
형식이 안전하지 않습니다. 유형 안전이 염려된다면 millhouse의 대답 이 맞습니다.
추가 세부 사항
명확히하기 위해 관찰 된 컴파일러 오류는 다음과 같습니다.
The method thenReturn(List<capture#1-of ? extends Number>) in the type OngoingStubbing<List<capture#1-of ? extends Number>> is not applicable for the arguments (List<capture#2-of ? extends Number>)
컴파일러가 when
호출 중에 첫 번째 와일드 카드 유형을 할당 한 다음 호출의 두 번째 와일드 카드 유형 thenReturn
이 동일한 지 확인할 수 없습니다 .
thenAnswer
와일드 카드 유형을 허용하는 동안 와일드 카드 유형 thenReturn
이 아닌 유형을 사용하므로이 문제가 발생하지 않는 것 같습니다 . Mockito의 OngoingStubbing 에서
OngoingStubbing<T> thenAnswer(Answer<?> answer);
OngoingStubbing<T> thenReturn(T value);
답변
나는 당신이 someList
알려진 값 으로로드 할 수 있기를 원한다고 가정 합니다. 다음 Answer<T>
은 템플릿 형식의 도우미 메서드와 함께 사용하여 모든 유형을 안전하게 유지하는 방법입니다.
@Test
public void testMockitoWithGenericsUsingAnswer()
{
DummyClass dummyClass = Mockito.mock(DummyClass.class);
Answer<List<Integer>> answer = setupDummyListAnswer(77, 88, 99);
Mockito.when(dummyClass.dummyMethod()).thenAnswer(answer);
...
}
private <N extends Number> Answer<List<N>> setupDummyListAnswer(N... values) {
final List<N> someList = new ArrayList<N>();
someList.addAll(Arrays.asList(values));
Answer<List<N>> answer = new Answer<List<N>>() {
public List<N> answer(InvocationOnMock invocation) throws Throwable {
return someList;
}
};
return answer;
}
답변
나는 어제 같은 것을 맞았다. @ nondescript1과 @millhouse의 대답은 해결 방법을 찾는 데 도움이되었습니다. 나는 거의 내 오류가 발생되지 않았기 때문에, 나는 그것이 약간 더 일반적인 만든 것을 제외하고, @millhouse과 같은 코드를 사용했습니다 java.util.List
,하지만 com.google.common.base.Optional
. 내 작은 도우미 메서드는 다음과 같은 유형 T
이 아니라 모든 유형을 허용합니다 List<T>
.
public static <T> Answer<T> createAnswer(final T value) {
Answer<T> dummy = new Answer<T>() {
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
return value;
}
};
return dummy;
}
이 도우미 메서드를 사용하면 다음과 같이 작성할 수 있습니다.
Mockito.when(dummyClass.dummyMethod()).thenAnswer(createAnswer(someList));
이것은 잘 컴파일되고 thenReturn(...)
메소드 와 동일한 작업을 수행합니다 .
누군가 Java 컴파일러에서 발생하는 오류가 컴파일러 버그인지 또는 코드가 실제로 잘못된 것인지 알고 있습니까?
답변
Java 8 이상을 사용하는 가장 우아한 솔루션이라고 생각할 때 더 많은 가시성을 제공하기 위해 fikovnik 의 의견 을 여기에 대한 답변 으로 바꾸고 있습니다.
Mockito 설명서를 사용하는 것이 좋습니다 doReturn()
(허용 대답에 제안) 마지막 수단으로 만.
대신, 질문에 설명 된 컴파일러 오류를 피하기 위해 권장 Mockito when()
접근 방식 thenAnswer()
과 람다를 사용할 수 있습니다 (도움말 방법 대신).
Mockito.when(mockedClass.mockedMethod()).thenAnswer(x -> resultList)