2012-07-23 26 views
201

मैं मॉकिटो 1.9.0 का उपयोग कर रहा हूं। मैं एक JUnit परीक्षण में एक वर्ग के एकल विधि के लिए व्यवहार नकली चाहते हैं, तो मैंमॉकिटो: विधि पर जासूसी करने की कोशिश कर रहा है मूल विधि

final MyClass myClassSpy = Mockito.spy(myInstance); 
Mockito.when(myClassSpy.method1()).thenReturn(myResults); 

समस्या है, दूसरी पंक्ति में, myClassSpy.method1() वास्तव में बुलाया जा रहा है है, एक अपवाद हो जाती है। मैक्स का उपयोग करने का एकमात्र कारण यह है कि बाद में, जब भी myClassSpy.method1() कहा जाता है, असली विधि नहीं कहा जाएगा और myResults ऑब्जेक्ट वापस कर दिया जाएगा।

MyClass एक अंतरफलक है और myInstance, कि के एक कार्यान्वयन है कि अगर मायने रखती है।

इस जासूसी व्यवहार को सही करने के लिए मुझे क्या करने की ज़रूरत है?

उत्तर

348

मुझे बोली the official documentation करते हैं:

असली वस्तुओं जासूसी पर महत्वपूर्ण मिल गया!

कभी-कभी जासूसों को रोकने के लिए (ऑब्जेक्ट) का उपयोग करना असंभव है। उदाहरण:

List list = new LinkedList(); 
List spy = spy(list); 

// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) 
when(spy.get(0)).thenReturn("foo"); 

// You have to use doReturn() for stubbing 
doReturn("foo").when(spy).get(0); 

आपके मामले में यह जाता है की तरह कुछ:

doReturn(resulstIWant).when(myClassSpy).method1(); 
+15

क्या होगा यदि मैं इस विधि का उपयोग और अपने मूल एक अभी भी बुलाया जा रहा है? क्या पैरामीटर के साथ समस्या हो सकती है? यहाँ पूरे परीक्षण है: http://pastebin.com/ZieY790P 'send' विधि –

+9

@EvgeniPetrov बुलाया जा रहा है, तो अपने मूल पद्धति अभी भी बुलाया जा रहा है यह शायद इसलिए है क्योंकि अपने मूल विधि अंतिम है। मॉकिटो अंतिम तरीकों का नकल नहीं करता है, और अंतिम तरीकों के मज़ाक के बारे में आपको चेतावनी नहीं दे सकता है। – MarcG

+0

क्या यह doThrow() के लिए भी संभव है? – Gobliins

19

मेरे मामले स्वीकार किए जाते हैं जवाब से अलग था। मैं एक उदाहरण है कि पैकेज में नहीं रहते थे के लिए एक पैकेज-निजी विधि नकली

package common; 

public class Animal { 
    void packageProtected(); 
} 

package instances; 

class Dog extends Animal { } 

और परीक्षण वर्गों

package common; 

public abstract class AnimalTest<T extends Animal> { 
    @Before 
    setup(){ 
    doNothing().when(getInstance()).packageProtected(); 
    } 

    abstract T getInstance(); 
} 

package instances; 

class DogTest extends AnimalTest<Dog> { 
    Dog getInstance(){ 
    return spy(new Dog()); 
    } 

    @Test 
    public void myTest(){} 
} 

संकलन सही है, लेकिन करने के लिए कोशिश कर रहा था जब यह सेटअप करने के लिए कोशिश करता है परीक्षण, यह इसके बजाय असली विधि का आह्वान करता है।

विधि या सार्वजनिक फिक्स मुद्दा रक्षा की, यद्यपि यह एक साफ समाधान नहीं है की घोषणा।

+0

मैं एक समान मुद्दे में भाग गया, लेकिन परीक्षण और पैकेज-निजी विधि एक ही पैकेज में थी। मुझे लगता है कि शायद मॉकिटो में सामान्य रूप से पैकेज-निजी तरीकों के साथ समस्याएं हैं। – Dave

7

टॉमसज़ नुर्कविचज़ का उत्तर पूरी कहानी नहीं बताना प्रतीत होता है!

एनबी मॉकिटो संस्करण: 1.10.1 9।

मैं बहुत अधिक मॉकिटो न्यूब हूं, इसलिए निम्न व्यवहार की व्याख्या नहीं कर सकता: यदि कोई विशेषज्ञ है जो इस उत्तर को बेहतर बना सकता है, तो कृपया बेझिझक महसूस करें।

प्रश्न में विधि यहाँ, getContentStringValue, नहींfinal और नहींstatic है।

इस लाइन मूल विधि getContentStringValue फोन करता है:

doReturn("dummy").when(im).getContentStringValue(anyInt(), isA(ScoreDoc.class)); 

इस लाइन नहीं है कॉल मूल विधि getContentStringValue:

doReturn("dummy").when(im).getContentStringValue(anyInt(), any(ScoreDoc.class)); 

कारण जो मैं उत्तर नहीं दे सकता के लिए, isA() का उपयोग करने के लिए doReturn के इरादे (?) "विधि को कॉल न करें" व्यवहार का कारण बनता है।

आइए यहां शामिल विधि हस्ताक्षर देखें: वे Matchers दोनों विधियां हैं। जावाडोक द्वारा दोनों को null लौटने के लिए कहा जाता है, जो आपके सिर को अपने आप में लाने में थोड़ा मुश्किल है। संभावित रूप से Class ऑब्जेक्ट पास किया गया है क्योंकि पैरामीटर की जांच की गई है लेकिन परिणाम या तो कभी गणना या त्याग नहीं किया गया है। यह देखते हुए कि null किसी भी वर्ग के लिए खड़ा हो सकता है और आप मॉक किए गए विधि को कॉल नहीं करने की उम्मीद कर रहे हैं, isA(...) और any(...) के हस्ताक्षर नहीं हो सकते हैं, केवल सामान्य पैरामीटर * <T> के बजाय null लौटाएं?

वैसे भी

:

public static <T> T isA(java.lang.Class<T> clazz) 

public static <T> T any(java.lang.Class<T> clazz) 

API दस्तावेज़ इस बारे में कोई सुराग नहीं देता है। ऐसा लगता है कि इस तरह की "कॉल विधि नहीं" व्यवहार की आवश्यकता "बहुत दुर्लभ" है। निजी तौर पर मैं इस तकनीक का उपयोग हर समय: आम तौर पर मुझे लगता है कि मॉकिंग में कुछ पंक्तियां शामिल हैं जो "दृश्य सेट करें" ... उसके बाद एक विधि को कॉल करके जो आपके द्वारा आयोजित किए गए नकली संदर्भ में दृश्य को "नाटक" करती है ... और जब आप दृश्यों की स्थापना कर रहे हैं और समर्थक आखिरी चीज चाहते हैं तो कलाकारों के लिए मंच छोड़ने के लिए और उनके दिल को अभिनय करना शुरू करें ...

लेकिन यह मेरे वेतन ग्रेड से परे है .. मैं किसी भी गुजरने वाले मॉकिटो उच्च पुजारी से स्पष्टीकरण आमंत्रित करता हूं ...

* सही शब्द "जेनेरिक पैरामीटर" है?

+0

मैं नहीं जानता कि अगर यह स्पष्टता कहते हैं या मामले की आगे confuses, लेकिन ईसा के बीच का अंतर() और किसी भी() कि ईसा वास्तव में जाँच टाइप करता है, जबकि किसी भी विधि का() परिवार बस बनाया गया था के प्रकार के कास्टिंग से बचने के लिए है बहस। –

+0

@ केविनवेल्कर धन्यवाद। और वास्तव में विधि नामों की एक निश्चित आत्म-स्पष्टीकरण गुणवत्ता में कमी नहीं है। हालांकि, मैं हालांकि, हल्के ढंग से, प्रतिभाशाली दस्तावेज न करने के लिए प्रतिभाशाली मॉकिटो डिजाइनरों के साथ समस्या उठाता हूं। इसमें कोई संदेह नहीं है कि मुझे मॉकिटो पर एक और पुस्तक पढ़ने की जरूरत है। वास्तव में पीएस "इंटरमीडिएट मॉकिटो" को पढ़ाने के लिए बहुत कम संसाधन प्रतीत होता है! –

+1

इतिहास यह है कि किसी भीXX विधियों को केवल टाइपकास्टिंग से निपटने के तरीके के रूप में बनाया गया था। फिर जब यह सुझाव दिया गया कि वे तर्क जांच जोड़ते हैं, तो वे मौजूदा एपीआई के उपयोगकर्ताओं को तोड़ना नहीं चाहते थे, इसलिए उन्होंने isA() परिवार बनाया। यह जानकर कि किसी भी() विधियों ने सभी प्रकार की जांच की होनी चाहिए, जब तक उन्होंने मॉकिटो 2. एक्स ओवरहाल (जो मैंने अभी तक कोशिश नहीं की है) में अन्य तोड़ने वाले बदलावों को पेश नहीं किया है। 2.x + में, anyX() विधियां isA() विधियों के लिए उपनाम हैं। –

1

मेरे मामले में, मॉकिटो 2.0 का उपयोग करके, मुझे वास्तविक कॉल को रोकने के लिए सभी() पैरामीटर को शून्य() में बदलना पड़ा।

+0

मत है कि 321 शीर्ष जवाब मतदान आप नीचे लाने के लिए, यह मेरी समस्या :) हल मैं कुछ घंटों के लिए इस के साथ संघर्ष कर रहे थे! –

0

मुझे मूल विधि को कॉल करने के लिए जासूसी के लिए एक और कारण मिला है।

किसी विचार को एक final वर्ग उपहास करने के लिए किया था, और MockMaker के बारे में पाया: यह हमारे वर्तमान तंत्र के लिए अलग तरह से काम करता है और यह एक अलग सीमाएं हैं और जैसा कि हम अनुभव और प्रयोक्ताओं की राय इकट्ठा करने के लिए चाहते हैं के रूप में

, इस सुविधा को उपलब्ध होने के लिए स्पष्ट रूप से सक्रिय किया जाना था; यह फ़ाइल src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker एक पंक्ति युक्त बनाने के द्वारा mockito विस्तार प्रणाली के माध्यम से किया जा सकता है: mock-maker-inline

स्रोत: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods

बाद मैं विलय कर दिया और मेरे मशीन के लिए उस फ़ाइल लाया, मेरे परीक्षण में विफल रहा है।

मुझे बस लाइन (या फ़ाइल) को हटा देना पड़ा, और spy() काम किया।