क्या मॉकिटोस आर्ग्यूमेंट कैपटोर का उपयोग करके विशिष्ट प्रकार की सूची पर कब्जा करने का एक तरीका है। यह काम नहीं करता है:
ArgumentCaptor<ArrayList<SomeType>> argument = ArgumentCaptor.forClass(ArrayList.class);
क्या मॉकिटोस आर्ग्यूमेंट कैपटोर का उपयोग करके विशिष्ट प्रकार की सूची पर कब्जा करने का एक तरीका है। यह काम नहीं करता है:
ArgumentCaptor<ArrayList<SomeType>> argument = ArgumentCaptor.forClass(ArrayList.class);
जवाबों:
नेस्टेड जेनरिक-समस्या से बचा जा सकता है @ कप्तान के एनोटेशन :
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()));
}
}
MockitoAnnotations.initMocks(this)
में @Before
के बजाय विधि एक धावक का उपयोग कर कि शामिल नहीं एक और धावक उपयोग करने की क्षमता। हालाँकि, +1, एनोटेशन इंगित करने के लिए धन्यवाद।
हाँ, यह सामान्य सामान्य समस्या है, मॉकिटो-विशिष्ट नहीं।
इसके लिए कोई क्लास ऑब्जेक्ट नहीं है ArrayList<SomeType>
, और इस प्रकार आप इस तरह के ऑब्जेक्ट को सुरक्षित रूप से टाइप नहीं कर सकते हैं Class<ArrayList<SomeType>>
।
आप ऑब्जेक्ट को सही प्रकार से डाल सकते हैं:
Class<ArrayList<SomeType>> listClass =
(Class<ArrayList<SomeType>>)(Class)ArrayList.class;
ArgumentCaptor<ArrayList<SomeType>> argument = ArgumentCaptor.forClass(listClass);
यह असुरक्षित डाले के बारे में कुछ चेतावनी देगा, और निश्चित रूप से अपने ArgumentCaptor वास्तव में बीच अंतर नहीं कर सकते हैं ArrayList<SomeType>
और ArrayList<AnotherType>
हो सकता है तत्वों का निरीक्षण के बिना।
(के रूप में, अन्य जवाब में बताया गया है, जबकि यह एक सामान्य जेनरिक समस्या है, वहाँ के साथ प्रकार-सुरक्षा की समस्या के लिए एक Mockito विशेष समाधान है @Captor
एनोटेशन। यह अभी भी एक के बीच भेद नहीं कर सकते हैं ArrayList<SomeType>
और एक ArrayList<OtherType>
।)
दसियों की टिप्पणी पर भी एक नज़र डालें । आप Pa canlo Ebermann से मूल कोड को इसमें बदल सकते हैं (बहुत सरल)
final ArgumentCaptor<List<SomeType>> listCaptor
= ArgumentCaptor.forClass((Class) List.class);
ArgumentCaptor<List<SimeType>> argument = ArgumentCaptor.forClass((Class) List.class);
@SuppressWarnings("unchecked")
तर्क कैप्चर परिभाषा रेखा के ऊपर एनोटेशन का उपयोग करें । इसके अलावा, कास्टिंग Class
निरर्थक है।
Class
मेरे परीक्षणों में कास्टिंग निरर्थक नहीं है।
यदि आप पुराने जावा-शैली (गैर प्रकार के सुरक्षित सामान्य) शब्दार्थ से डरते नहीं हैं, तो यह भी काम करता है और यथोचित सरल है:
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"));
@ दसियों की और @ पल्किनो की टिप्पणियों (@ कुगरडैप के लिए भी कुदोस) के आधार पर, सूची तर्क कैप्चर बनाने के लिए निम्नलिखित एक सरल उपाय है जो "अनियंत्रित या असुरक्षित संचालन" चेतावनी को निष्क्रिय करता है।
@SuppressWarnings("unchecked")
final ArgumentCaptor<List<SomeType>> someTypeListArgumentCaptor =
ArgumentCaptor.forClass(List.class);
पूर्ण उदाहरण यहाँ और इसी पास CI निर्माण और परीक्षण रन यहाँ ।
हमारी टीम कुछ समय से हमारे यूनिट परीक्षणों में इसका उपयोग कर रही है और यह हमारे लिए सबसे सीधा समाधान है।
जूनियर के पुराने संस्करण के लिए, आप कर सकते हैं
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();
इस सटीक समस्या के बारे में मॉकिटो के गिटहब में एक खुला मुद्दा है।
मुझे एक साधारण हल मिला है जो आपको अपने परीक्षणों में एनोटेशन का उपयोग करने के लिए मजबूर नहीं करता है:
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>>>>() {
}
);
यह काम करता है, क्योंकि मॉकिटो को वास्तव में किसी भी प्रकार की जानकारी की आवश्यकता नहीं है (उदाहरण के लिए, धारावाहिकों के विपरीत)।
ArrayList
)। आप हमेशाList
इंटरफ़ेस का उपयोग कर सकते हैं , और यदि आप इस तथ्य का प्रतिनिधित्व करना चाहते हैं, कि यह सहसंयोजक है, तो आप उपयोग कर सकते हैंextends
:ArgumentCaptor<? extends List<SomeType>>