모키토로 특정 유형의 목록을 캡처하는 방법
모키토스 인수캡토어를 사용하여 특정 유형의 목록을 캡처할 수 있는 방법이 있는가?이 작업은 작동하지 않음:
ArgumentCaptor<ArrayList<SomeType>> argument = ArgumentCaptor.forClass(ArrayList.class);
중첩된 제네릭-문제점은 @Captor 주석으로 방지할 수 있다.
public class Test{
@Mock
private Service service;
@Captor
private ArgumentCaptor<ArrayList<SomeType>> captor;
@Before
public void init(){
MockitoAnnotations.initMocks(this);
}
@Test
public void shouldDoStuffWithListValues() {
//...
verify(service).doStuff(captor.capture()));
}
}
그래, 이건 일반적인 제네릭 문제지 모키토 특유의 문제가 아니야.
에 대한 클래스 개체가 없음ArrayList<SomeType>
따라서, 타이핑을 통해 이러한 개체를 필요한 방법으로 전달할 수 없음Class<ArrayList<SomeType>>
.
개체를 올바른 유형으로 캐스트할 수 있음:
Class<ArrayList<SomeType>> listClass =
(Class<ArrayList<SomeType>>)(Class)ArrayList.class;
ArgumentCaptor<ArrayList<SomeType>> argument = ArgumentCaptor.forClass(listClass);
이것은 안전하지 않은 깁스에 대한 경고를 줄 것이고, 물론 당신의 Captor는 실제로 구별할 수 없다.ArrayList<SomeType>
그리고ArrayList<AnotherType>
원소를 검사하지 않고 말이야
(다른 답변에서 언급한 바와 같이, 이것이 일반적인 제네릭 문제인 반면, 본문에는 다음과 같은 유형 안전 문제에 대한 모키토 특유의 해결책이 있다.@Captor
주석을 달다그것은 여전히 a를 구별할 수 없다.ArrayList<SomeType>
그리고ArrayList<OtherType>
.)
편집:
텐슈의 댓글도 한 번 보시죠.원래 코드를 다음과 같이 단순화된 버전으로 변경할 수 있다.
final ArgumentCaptor<List<SomeType>> listCaptor
= ArgumentCaptor.forClass((Class) List.class);
오래된 Java 스타일(안전하지 않은 일반적) 의미론을 두려워하지 않는 경우, 이 또한 작동하며 단순하다.
ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class);
verify(subject).method(argument.capture()); // run your code
List<SomeType> list = argument.getValue(); // first captured List, etc.
List<String> mockedList = mock(List.class);
List<String> l = new ArrayList();
l.add("someElement");
mockedList.addAll(l);
ArgumentCaptor<List> argumentCaptor = ArgumentCaptor.forClass(List.class);
verify(mockedList).addAll(argumentCaptor.capture());
List<String> capturedArgument = argumentCaptor.<List<String>>getValue();
assertThat(capturedArgument, hasItem("someElement"));
@tenshi 및 @pkalinow의 의견(@rogerdpack에 대한 쿠도)에 근거하여, 목록 인수 캡쳐를 생성하기 위한 간단한 해결책은 다음과 같다. 또한 "확인되지 않았거나 안전하지 않은 운영 사용" 경고를 비활성화한다.
@SuppressWarnings("unchecked")
final ArgumentCaptor<List<SomeType>> someTypeListArgumentCaptor =
ArgumentCaptor.forClass(List.class);
여기에 전체 예와 여기에 해당하는 통과 CI 구축 및 테스트 실행.
우리 팀은 이것을 우리 유닛 테스트에서 오랫동안 사용해 왔고 이것은 우리에게 가장 간단한 해결책처럼 보인다.
이전 버전의 Junit은 다음과 같이 할 수 있다.
Class<Map<String, String>> mapClass = (Class) Map.class;
ArgumentCaptor<Map<String, String>> mapCaptor = ArgumentCaptor.forClass(mapClass);
나는 안드로이드 앱에서 테스트 활동에도 같은 문제가 있었어.나는 사용했다.ActivityInstrumentationTestCase2
그리고MockitoAnnotations.initMocks(this);
효과가 없었어나는 이 문제를 다른 분야와 함께 풀었다.예를 들면 다음과 같다.
class CaptorHolder {
@Captor
ArgumentCaptor<Callback<AuthResponse>> captor;
public CaptorHolder() {
MockitoAnnotations.initMocks(this);
}
}
활동 테스트 방법에서 다음을 수행하십시오.
HubstaffService hubstaffService = mock(HubstaffService.class);
fragment.setHubstaffService(hubstaffService);
CaptorHolder captorHolder = new CaptorHolder();
ArgumentCaptor<Callback<AuthResponse>> captor = captorHolder.captor;
onView(withId(R.id.signInBtn))
.perform(click());
verify(hubstaffService).authorize(anyString(), anyString(), captor.capture());
Callback<AuthResponse> callback = captor.getValue();
모키토의 GitHub에는 이 정확한 문제에 대한 공개적인 이슈가 있다.
나는 당신이 당신의 테스트에서 주석을 사용하도록 강요하지 않는 간단한 해결 방법을 찾았다.
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.MockitoAnnotations;
public final class MockitoCaptorExtensions {
public static <T> ArgumentCaptor<T> captorFor(final CaptorTypeReference<T> argumentTypeReference) {
return new CaptorContainer<T>().captor;
}
public static <T> ArgumentCaptor<T> captorFor(final Class<T> argumentClass) {
return ArgumentCaptor.forClass(argumentClass);
}
public interface CaptorTypeReference<T> {
static <T> CaptorTypeReference<T> genericType() {
return new CaptorTypeReference<T>() {
};
}
default T nullOfGenericType() {
return null;
}
}
private static final class CaptorContainer<T> {
@Captor
private ArgumentCaptor<T> captor;
private CaptorContainer() {
MockitoAnnotations.initMocks(this);
}
}
}
여기서 무슨 일이 일어나는가 하면, 우리는 새로운 클래스를 만들게 된다.@Captor
주석을 달아서 캡처를 삽입한다.그리고 나서 우리는 포로를 추출해서 우리의 정적 방법에서 돌려준다.
테스트에서 다음과 같이 사용할 수 있다.
ArgumentCaptor<Supplier<Set<List<Object>>>> fancyCaptor = captorFor(genericType());
아니면 잭슨의 구문과 비슷한 구문으로.TypeReference
:
ArgumentCaptor<Supplier<Set<List<Object>>>> fancyCaptor = captorFor(
new CaptorTypeReference<Supplier<Set<List<Object>>>>() {
}
);
모키토는 실제로 (예를 들어 시리얼라이저와는 달리) 어떤 유형 정보도 필요로 하지 않기 때문에 효과가 있다.
참조URL: https://stackoverflow.com/questions/5606541/how-to-capture-a-list-of-specific-type-with-mockito
'IT이야기' 카테고리의 다른 글
Vue Js에서 문자열 변수 스키마로 입력 이름 필드를 만드는 방법? (0) | 2022.05.13 |
---|---|
C에서 지수를 어떻게 하느냐? (0) | 2022.05.13 |
강력한 비동기 검증자 - 어떻게 철회할 것인가? (0) | 2022.05.13 |
Java System.currentTimeMillis를 테스트 시간 민감 코드에 대해 재정의 (0) | 2022.05.13 |
Java에서 long을 int로 변환하려면 어떻게 해야 하는가? (0) | 2022.05.12 |