मॉकिटो के साथ शून्य तरीकों को कैसे मॉक करें


937

शून्य वापसी प्रकार के साथ तरीकों का मजाक कैसे करें?

मैंने एक पर्यवेक्षक पैटर्न लागू किया है लेकिन मैं इसे मॉकिटो के साथ मजाक नहीं कर सकता क्योंकि मैं नहीं जानता कि कैसे।

और मैंने इंटरनेट पर एक उदाहरण खोजने की कोशिश की लेकिन सफल नहीं हुआ।

मेरी कक्षा इस तरह दिखती है:

public class World {

    List<Listener> listeners;

    void addListener(Listener item) {
        listeners.add(item);
    }

    void doAction(Action goal,Object obj) {
        setState("i received");
        goal.doAction(obj);
        setState("i finished");
    }

    private string state;
    //setter getter state
} 

public class WorldTest implements Listener {

    @Test public void word{
    World  w= mock(World.class);
    w.addListener(this);
    ...
    ...

    }
}

interface Listener {
    void doAction();
}

मॉक के साथ सिस्टम को ट्रिगर नहीं किया गया है।

मैं उपर्युक्त प्रणाली की स्थिति दिखाना चाहता हूं। और उनके अनुसार ही मुखर करें।


6
नकली पर शून्य तरीकों डिफ़ॉल्ट रूप से कुछ भी नहीं है कि खबरदार!
रेखा

1
@ लाईन, यही मैं ढूंढ रहा था। आपके कहने के बाद यह स्पष्ट प्रतीत होता है। लेकिन यह एक मॉकिंग सिद्धांत को उजागर करता है: आपको केवल उनके प्रभाव के लिए मॉकड क्लास के तरीकों का मजाक बनाने की जरूरत है, जैसे रिटर्न वैल्यू या अपवाद। धन्यवाद!
एलनजोम

जवाबों:


1144

मॉकिटो एपीआई डॉक्स पर एक नज़र डालें । लिंक किए गए दस्तावेज़ का उल्लेख के रूप में (प्वाइंट # 12) आप में से किसी का उपयोग कर सकते doThrow(), doAnswer(), doNothing(), doReturn()Mockito ढांचे से तरीकों में से परिवार शून्य तरीकों उपहास करने के लिए।

उदाहरण के लिए,

Mockito.doThrow(new Exception()).when(instance).methodName();

या यदि आप इसे अनुवर्ती व्यवहार के साथ जोड़ना चाहते हैं,

Mockito.doThrow(new Exception()).doNothing().when(instance).methodName();

यह मानते हुए कि आप setState(String s)नीचे क्लास वर्ल्ड में सेटर का मजाक उड़ाते हुए देख रहे हैं , यह कोड doAnswerमॉक टू मेक का उपयोग करता है setState

World  mockWorld = mock(World.class); 
doAnswer(new Answer<Void>() {
    public Void answer(InvocationOnMock invocation) {
      Object[] args = invocation.getArguments();
      System.out.println("called with arguments: " + Arrays.toString(args));
      return null;
    }
}).when(mockWorld).setState(anyString());

8
@qualidafial: हाँ, मुझे लगता है कि Void के लिए मानकीकरण बेहतर होगा क्योंकि यह बेहतर बताता है कि मुझे रिटर्न प्रकार में कोई दिलचस्पी नहीं है। मुझे इस निर्माण की जानकारी नहीं थी, इसे इंगित करने के लिए धन्यवाद।
सतेश

2
doThrow # 5 अब है (मेरे लिए भी dohhrow का उपयोग करके यह संदेश "" शून्य प्रकार यहाँ अनुमति नहीं है ", अनुयायियों के लिए तय किया गया है ...)
rogerdpack

@qualidafial: मुझे लगता है कि उत्तर का वापसी प्रकार। शेयर कॉल वह नहीं है जो मूल विधि में वापस हो जाता है, यह वह है जिसे doAnswer कॉल पर लौटा दिया जाता है, संभवतः यदि आप अपने परीक्षण में उस मान के साथ कुछ और करना चाहते हैं।
बारह

1
:( अमरूद doNothing () में (जब (mockLimiterReject) .setRate (100) कॉलिंग रेट रेटिमिटर के मॉक संस्करण 16.0.1 को मॉक करने की कोशिश में। इसलिए यह मेरी निर्धारित विधि का मजाक नहीं उड़ाया :( लेकिन इसके बजाय इसे बुलाया :(
डीन हिलर

2
@DeanHiller नोटिस जो setRate()है final, और इसलिए उसका मजाक नहीं उड़ाया जा सकता। इसके बजाय create()एक ऐसे उदाहरण को आज़माएं जो आपको चाहिए। मजाक करने की जरूरत नहीं होनी चाहिए RateLimiter
dimo414

113

मुझे लगता है कि मुझे उस प्रश्न का एक सरल उत्तर मिल गया है, केवल एक विधि के लिए वास्तविक विधि को कॉल करने के लिए (भले ही इसमें शून्य रिटर्न हो) आप ऐसा कर सकते हैं:

Mockito.doCallRealMethod().when(<objectInstance>).<method>();
<objectInstance>.<method>();

या, आप ऐसा करने वाले उस वर्ग के सभी तरीकों के लिए वास्तविक विधि कह सकते हैं:

<Object> <objectInstance> = mock(<Object>.class, Mockito.CALLS_REAL_METHODS);

13
यहीं असली जवाब है। जासूसी () विधि ठीक काम करती है, लेकिन आम तौर पर तब आरक्षित होती है जब आप चाहते हैं कि वस्तु सामान्य रूप से सबसे अधिक काम करे।
बिगगुस्जिमस

1
इसका क्या मतलब है? क्या आप वास्तव में तरीकों को बुला रहे हैं? मैंने पहले कभी मॉकिटो का इस्तेमाल नहीं किया है।
obesechicken13

हां, नकली वास्तविक तरीकों को कहेंगे। यदि आप @Mock का उपयोग करते हैं, तो आप उसी परिणाम को प्राप्त करने के लिए: @Mock (उत्तर = उत्तर.संख्या_CALS_REAL_METHODS) का उपयोग कर सकते हैं।
एले

70

@Sateesh ने कहा कि जब आप परीक्षण को रोकने से रोकने के लिए केवल एक शून्य विधि का उपयोग करना चाहते हैं, तो आप Spyइस तरह से उपयोग कर सकते हैं :

World world = new World();
World spy = Mockito.spy(world);
Mockito.doNothing().when(spy).methodToMock();

जब आप अपना परीक्षण चलाना चाहते हैं, तो सुनिश्चित करें कि आप spyऑब्जेक्ट पर परीक्षण में विधि को कॉल करते हैं न कि worldऑब्जेक्ट पर। उदाहरण के लिए:

assertEquals(0,spy.methodToTestThatShouldReturnZero());

57

तथाकथित समस्या का समाधान एक प्रयोग है spy Mockito.spy (...) के बजाय एक mock Mockito.mock (..)

जासूस हमें आंशिक रूप से मज़ाक करने में सक्षम बनाता है। इस मामले में मॉकिटो अच्छा है। क्योंकि आपके पास वह वर्ग है जो पूर्ण नहीं है, ऐसे में आप इस कक्षा में कुछ आवश्यक स्थान का मजाक उड़ाते हैं।


3
मैं यहां इसलिए लड़खड़ाया क्योंकि मुझे भी इसी तरह की समस्या थी (संयोग से, एक विषय / ऑब्जर्वर इंटरेक्शन का परीक्षण करने के लिए हुआ)। मैं पहले से ही एक जासूस का उपयोग कर रहा हूं, लेकिन मैं कुछ अलग करने के लिए 'सब्जेक्टचेंज' पद्धति चाहता हूं। मैं `सत्यापित (पर्यवेक्षक)। SubjectChanged (विषय) का उपयोग केवल यह देखने के लिए कर सकता था कि विधि को बुलाया गया था। लेकिन, किसी कारण के लिए, मैं इस पद्धति को ओवरराइड करना चाहूंगा। उसके लिए, सतेश के दृष्टिकोण का संयोजन और यहाँ आपका उत्तर जाने का रास्ता था ...
galeale

32
नहीं, ऐसा करना वास्तव में शून्य तरीकों का मजाक उड़ाने में मदद नहीं करेगा। यह चाल सातेश के उत्तर में सूचीबद्ध चार मॉकिटो स्थैतिक तरीकों में से एक का उपयोग करना है।
दाऊद इब्न करीम

2
आपके प्रश्न के लिए @Gard इस stackoverflow.com/questions/1087339/… पर एक नज़र डालें ।
ibrahimyilmaz

यह डोजेंट वास्तव में काम करता है।
नीलोत्पल

34

सबसे पहले: आपको हमेशा मॉकिटो स्थैतिक आयात करना चाहिए, इस तरह से कोड बहुत अधिक पठनीय (और सहज) होगा:

import static org.mockito.Mockito.*;

आंशिक मॉकिंग के लिए और अभी भी बाकी मॉकिटो पर मूल कार्यक्षमता रखने के लिए "स्पाई" प्रदान करता है।

आप इसका उपयोग इस प्रकार कर सकते हैं:

private World world = spy(World.class);

निष्पादित होने से एक विधि को समाप्त करने के लिए आप कुछ इस तरह का उपयोग कर सकते हैं:

doNothing().when(someObject).someMethod(anyObject());

एक "तब" के साथ "जब" एक विधि का उपयोग करने के लिए कुछ कस्टम व्यवहार देने के लिए:

doReturn("something").when(this.world).someMethod(anyObject());

अधिक उदाहरणों के लिए कृपया डॉक में उत्कृष्ट मॉकिटो नमूने देखें।


4
स्थैतिक आयात का इसे अधिक पठनीय बनाने के साथ क्या करना है?
jsonbourne

2
सचमुच कुछ भी नहीं।
specializt

2
मुझे लगता है कि यह स्वाद की बात है, मैं सिर्फ एक अंग्रेजी वाक्य की तरह स्टेटमेंट लुक (लगभग) पसंद करता हूं, और Class.methodname ()। कुछ () बनाम मेथडनाम () .something कम द्रवयुक्त पठनीय है।
fl0w

1
यदि आप एक टीम पर काम करते हैं, तो स्थैतिक आयात करता है यह किसी और के लिए गधे में एक दर्द बनाता है यह देखने के लिए कि विधि कहां से आ रही है, क्योंकि आयात में अक्सर वाइल्डकार्ड होता है।
LowKeyEnergy

यह सही है, हालांकि टेस्ट कोड और मॉकिटो के लिए यह स्पष्ट होना चाहिए और कोई समस्या नहीं है।
fl0w

26

मॉकिटो के साथ शून्य विधियों को कैसे मॉक करें - दो विकल्प हैं:

  1. doAnswer - अगर हम चाहते हैं कि हमारा नकली तरीका कुछ करने का हो (शून्य होने के बावजूद व्यवहार का मजाक उड़ाए)।
  2. doThrow- फिर वहाँ है Mockito.doThrow()अगर आप नकली शून्य विधि से एक अपवाद फेंकना चाहते हैं।

निम्नलिखित इसका उपयोग करने का एक उदाहरण है (एक आदर्श उपयोग नहीं है लेकिन सिर्फ मूल उपयोग को चित्रित करना चाहता था)।

@Test
public void testUpdate() {

    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            Object[] arguments = invocation.getArguments();
            if (arguments != null && arguments.length > 1 && arguments[0] != null && arguments[1] != null) {

                Customer customer = (Customer) arguments[0];
                String email = (String) arguments[1];
                customer.setEmail(email);

            }
            return null;
        }
    }).when(daoMock).updateEmail(any(Customer.class), any(String.class));

    // calling the method under test
    Customer customer = service.changeEmail("old@test.com", "new@test.com");

    //some asserts
    assertThat(customer, is(notNullValue()));
    assertThat(customer.getEmail(), is(equalTo("new@test.com")));

}

@Test(expected = RuntimeException.class)
public void testUpdate_throwsException() {

    doThrow(RuntimeException.class).when(daoMock).updateEmail(any(Customer.class), any(String.class));

    // calling the method under test
    Customer customer = service.changeEmail("old@test.com", "new@test.com");

}
}

आप अपनी पोस्ट में मॉकिटो के साथ शून्य विधि का मॉक और टेस्ट करने के तरीके के बारे में अधिक जानकारी पा सकते हैं मॉकिटो के साथ मॉक कैसे करें (उदाहरणों के साथ एक व्यापक गाइड)


1
महान उदाहरण। नोट: जावा 8 में, यह एक अनाम वर्ग के बजाय एक लैम्ब्डा का उपयोग करने के लिए थोड़ा अच्छा हो सकता है: 'doAnswer ((उत्तर <शून्य>) इनवोकेशन -> {// CODE})। जब (madInstance) .add (विधि) ()); '
miwe

16

गुच्छा में एक और उत्तर जोड़ना (कोई सज़ा नहीं) ...

यदि आप जासूस का उपयोग नहीं करना चाहते हैं तो आपको doAnswer विधि को कॉल करने की आवश्यकता है। हालाँकि, आपको अपना स्वयं का उत्तर देने की आवश्यकता नहीं है । कई डिफ़ॉल्ट कार्यान्वयन हैं। विशेष रूप से, CealRealMethods

व्यवहार में, यह कुछ इस तरह दिखता है:

doAnswer(new CallsRealMethods()).when(mock)
        .voidMethod(any(SomeParamClass.class));

या:

doAnswer(Answers.CALLS_REAL_METHODS.get()).when(mock)
        .voidMethod(any(SomeParamClass.class));

16

जावा 8 में इसे थोड़ा साफ किया जा सकता है, यह मानते हुए कि आपके लिए एक स्थिर आयात है org.mockito.Mockito.doAnswer:

doAnswer(i -> {
  // Do stuff with i.getArguments() here
  return null;
}).when(*mock*).*method*(*methodArguments*);

यह return null;महत्वपूर्ण है और इसके बिना यह संकलन कुछ अस्पष्ट त्रुटियों के साथ विफल हो जाएगा क्योंकि यह इसके लिए एक उपयुक्त ओवरराइड नहीं ढूंढ पाएगा doAnswer

उदाहरण के लिए, ExecutorServiceजो तुरंत उपयोग किए जा सकने वाले किसी भी Runnableपास को तुरंत निष्पादित करता है execute():

doAnswer(i -> {
  ((Runnable) i.getArguments()[0]).run();
  return null;
}).when(executor).execute(any());

2
एक पंक्ति में: Mockito.doAnswer ((i) -> null) .when (उदाहरण) .method (कोई ());
अक्षय थोरवे

जब आप वास्तव में मेरे साथ सामान करना चाहते हैं, तो @AkshayThorve काम नहीं करता है।
टिम बी

7

मुझे लगता है कि आपकी समस्याएं आपके परीक्षण संरचना के कारण हैं। मैंने परीक्षण वर्ग में इंटरफेस को लागू करने की पारंपरिक विधि के साथ मजाक करना मुश्किल पाया है (जैसा कि आपने यहां किया है)।

यदि आप श्रोता को मॉक के रूप में कार्यान्वित करते हैं तो आप सहभागिता को सत्यापित कर सकते हैं।

Listener listener = mock(Listener.class);
w.addListener(listener);
world.doAction(..);
verify(listener).doAction();

इससे आपको संतुष्ट होना चाहिए कि 'दुनिया ’सही काम कर रही है।


0

Mockito.doThrow का उपयोग निम्नानुसार करें:

Mockito.doThrow(new Exception()).when(instance).methodName();

आप इस अच्छे उदाहरण की कोशिश कर सकते हैं:

public void testCloseStreamOnException() throws Exception {
    OutputStream outputStream = Mockito.mock(OutputStream.class);
    IFileOutputStream ifos = new IFileOutputStream(outputStream);
    Mockito.doThrow(new IOException("Dummy Exception")).when(outputStream).flush();
    try {
      ifos.close();
      fail("IOException is not thrown");
    } catch (IOException ioe) {
      assertEquals("Dummy Exception", ioe.getMessage());
    }
    Mockito.verify(outputStream).close();
  }

स्रोत: http://apisonar.com/java-examples/org.mockito.Mockito.doThrow.html#Example-19

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.