मॉकिटो के तर्क का उदाहरण कैप्टन


141

क्या कोई कृपया मुझे एक उदाहरण प्रदान कर सकता है जिसमें दिखाया जा सकता है कि org.mockito.ArgumentCaptorकक्षा का उपयोग कैसे किया जाए और यह मॉकिटो के साथ प्रदान किए जाने वाले सरल मिलानकर्ताओं से कैसे भिन्न है ।

मैंने प्रदान किए गए मॉकिटो दस्तावेज़ पढ़े, लेकिन वे इसे स्पष्ट रूप से स्पष्ट नहीं करते हैं, उनमें से कोई भी इसे स्पष्टता के साथ समझाने में सक्षम नहीं है।

जवाबों:


187

मैं इस बात से सहमत हूं कि @fge ने और क्या कहा। उदाहरण देखते हैं। विचार करें कि आपके पास एक विधि है:

class A {
    public void foo(OtherClass other) {
        SomeData data = new SomeData("Some inner data");
        other.doSomething(data);
    }
}

अब यदि आप आंतरिक डेटा की जांच करना चाहते हैं, तो आप कैप्चर का उपयोग कर सकते हैं:

// Create a mock of the OtherClass
OtherClass other = mock(OtherClass.class);

// Run the foo method with the mock
new A().foo(other);

// Capture the argument of the doSomething function
ArgumentCaptor<SomeData> captor = ArgumentCaptor.forClass(SomeData.class);
verify(other, times(1)).doSomething(captor.capture());

// Assert the argument
SomeData actual = captor.getValue();
assertEquals("Some inner data", actual.innerData);

यदि doSomething(data)उत्परिवर्तन होता है innerData, तो क्या वह परिवर्तन मौजूद assertEquals("Some inner data", actual.innerData)होगा, या निष्पादित होने से पहलेinnerData कब्जा कर लिया जाएगा ? doSomething
कोरी क्लेन

@CoryKlein यह OtherClassएक मॉक है, और जैसा कि अब परिभाषित है कि doSomething()वसीयत वास्तविक रूप से कुछ भी नहीं करेगी, यह बस उस ऑब्जेक्ट को रिकॉर्ड करती है जो पारित किया गया था। इसका मतलब है कि इसे doSomethingनिष्पादित किया जाएगा जैसा कि निष्पादित होने से पहले है।
स्लाव शापिटलनी

3
में verify, times(1)डिफ़ॉल्ट है और छोड़ा जा सकता है।
inego

ArgumentCaptor को कैसे पता चलता है कि foo (अन्य) तब से हुआ है जब उसे foo (अन्य) कॉल के बाद ही तत्काल किया जाता है?
AvramPop

1
@AvramPop जो जानता है कि यह नकली वस्तु है। इसमें नकली के बारे में बहुत सारी जानकारी शामिल है। उस सभी सूचनाओं के अंदर यह प्रत्येक विधि के लिए कॉल इतिहास समाहित करता है, जिसमें यह पैरामीटर है। जब आप verifyविधि को कॉल करते हैं , तो यह उस सूचना का उपयोग उस सत्यापन के खिलाफ मैच चलाने के लिए करता है जो आप कर रहे हैं। प्रत्येक पैरामीटर के लिए यह पूछता है कि क्या यह उस विशिष्ट कॉल से मेल खाता है जो वह चेक करता है। जब ArgumentCaptor की जाँच की जाती है, तो यह केवल उन मूल्यों को संग्रहीत करता है जिन्हें इसके साथ लागू किया गया था जब verifyसमाप्त होता है, यह सभी प्रासंगिक इनवोकेशन रखता है। यह लगभग कैसे काम करता है। आशा है कि यह मदद करता है
स्लाव शापिटलनी

35

दो मुख्य अंतर हैं:

  • जब आप एक भी तर्क पर कब्जा कर लेते हैं, तो आप इस तर्क पर अधिक स्पष्ट परीक्षण कर सकते हैं, और अधिक स्पष्ट कोड के साथ;
  • एक ArgumentCaptorपर कब्जा कर सकते हैं और अधिक बार से।

उत्तरार्द्ध को स्पष्ट करने के लिए, यह कहें: आपके पास:

final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);

verify(x, times(4)).someMethod(captor.capture()); // for instance

तब कैप्चर आपको सभी 4 तर्कों तक पहुंच प्रदान करने में सक्षम होगा, जिसे आप बाद में अलग-अलग कर सकते हैं।

यह या वास्तव में किसी भी संख्या में तर्क, चूंकि VerificationModeएक निश्चित संख्या में आह्वान तक सीमित नहीं है; किसी भी घटना में, यदि आप चाहें तो कैप्शन आपको उन सभी तक पहुंच प्रदान करेगा।

इसका यह भी लाभ है कि इस तरह के परीक्षण अपने स्वयं के ArgumentMatcherएस को लागू करने की तुलना में लिखने के लिए (इम्हो) बहुत आसान हैं - खासकर यदि आप मुखर के साथ मॉकिटो को जोड़ते हैं।

ओह, और कृपया JUnit के बजाय TestNG का उपयोग करने पर विचार करें।


1
क्या होगा यदि विधि में कई पैरामीटर पारित किए जाते हैं - सभी विभिन्न प्रकार के? आप वास्तव में यह कैसे सत्यापित करते हैं कि बूलियन पैरामीटर सही था , उदाहरण के लिए।
इगोरगानापोलस्की

21
क्या आप अपनी टिप्पणी के लिए स्पष्टीकरण दे सकते हैं: ओह, और कृपया JUnit के बजाय TestNG का उपयोग करने पर विचार करें। । इस पर विचार क्यों? क्यों बदला?
नवगृहण

1
@IgorGanapolsky आप बस एक और तर्क जोड़ें। ArgumentCaptor <BigDecimal> arg = ArgumentCaptor.forClass (BigDecimal.class); ArgumentCaptor <string> arg2 = ArgumentCaptor.forClass (String.class); माइकल माइकल = नया माइकल (); michael.sayHi (जे); सत्यापित करें (j)। saySomething (arg.capture (), arg2.capture ()); System.out.println ("value is" + arg.getValue ()); System.out.println ("string is" + arg2.getValue ());
जोंविक0831

12

पूरी जाँच करने के लिए चरण निम्न हैं:

कैप्टर तैयार करें:

ArgumentCaptor<SomeArgumentClass> someArgumentCaptor = ArgumentCaptor.forClass(SomeArgumentClass.class);

घटक (परीक्षण के तहत विषय के सहयोगी) समय (1) पर निर्भर करने के लिए कॉल को सत्यापित करें, डिफ़ॉल्ट मान है, इसलिए इसे जोड़ने की आवश्यकता नहीं है।

verify(dependentOnComponent, times(1)).send(someArgumentCaptor.capture());

सहयोगी को तर्क पास करवाएं

SomeArgumentClass someArgument = messageCaptor.getValue();

someArgument मुखरता के लिए उपयोग किया जा सकता है


-2

यहां मैं आपको एक कॉलबैक विधि का एक उचित उदाहरण दे रहा हूं। तो मान लें कि हमारे पास विधि लॉगिन जैसी विधि है ():

 public void login() {
    loginService = new LoginService();
    loginService.login(loginProvider, new LoginListener() {
        @Override
        public void onLoginSuccess() {
            loginService.getresult(true);
        }

        @Override
        public void onLoginFaliure() {
            loginService.getresult(false);

        }
    });
    System.out.print("@@##### get called");
}

मैंने उदाहरण के लिए और अधिक स्पष्ट करने के लिए यहां सभी सहायक वर्ग को रखा: loginService वर्ग

public class LoginService implements Login.getresult{
public void login(LoginProvider loginProvider,LoginListener callback){

    String username  = loginProvider.getUsername();
    String pwd  = loginProvider.getPassword();
    if(username != null && pwd != null){
        callback.onLoginSuccess();
    }else{
        callback.onLoginFaliure();
    }

}

@Override
public void getresult(boolean value) {
    System.out.print("login success"+value);
}}

और हमारे पास श्रोता LoginListener है:

interface LoginListener {
void onLoginSuccess();

void onLoginFaliure();

}

अब मैं सिर्फ कक्षा लॉगिन की विधि लॉगिन () का परीक्षण करना चाहता था

 @Test
public void loginTest() throws Exception {
    LoginService service = mock(LoginService.class);
    LoginProvider provider = mock(LoginProvider.class);
    whenNew(LoginProvider.class).withNoArguments().thenReturn(provider);
    whenNew(LoginService.class).withNoArguments().thenReturn(service);
    when(provider.getPassword()).thenReturn("pwd");
    when(provider.getUsername()).thenReturn("username");
    login.getLoginDetail("username","password");

    verify(provider).setPassword("password");
    verify(provider).setUsername("username");

    verify(service).login(eq(provider),captor.capture());

    LoginListener listener = captor.getValue();

    listener.onLoginSuccess();

    verify(service).getresult(true);

टेस्ट क्लास के ऊपर एनोटेशन जोड़ना न भूलें

@RunWith(PowerMockRunner.class)
@PrepareForTest(Login.class)

1
क्या यह ArgumentCaptor का संदर्भ नहीं देना चाहिए?
फेलिप मार्टिंस मेलो

हाँ, हम विधि लॉगिन () को लॉगिन लॉगिन में लॉग इन कर रहे हैं (LoginProvider loginProvider, LoginListener कॉलबैक)
विक्रम सिंह

captorआपके उत्तर में परिभाषित कहां है ?
tom_mai78101

ArgumentCaptor <LoginListener> listenerCaptor = ArgumentCaptor.forClass (LoginListener.class);
विक्रम सिंह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.