2012-03-31 16 views
7

क्या यह मॉकिटो का उपयोग करना संभव है और वैकल्पिक रूप से पावरमॉक को सुपरक्लास S का नकल करने के लिए संभव है कि S पर सुपरक्लास के लिए कोई भी कॉल (S() कन्स्ट्रक्टर को कॉल सहित) मजाक कर रहे हैं? तो नीचे दिए गए उदाहरण का उपयोग करके, यदि मैं S को MockS के साथ मॉकिटो का उपयोग करके प्रतिस्थापित करता हूं, तो super() पर कॉल MockS में कन्स्ट्रक्टर का उपयोग करेगा?क्या मैं मॉकिटो/पावरमॉक के साथ सुपरक्लास के कन्स्ट्रक्टर का नकल कर सकता हूं?

class S { 
    S() { 
     // Format user's hard drive, call 911, and initiate self-destruct 
    } 
} 

class T extends S { 
    T() { 
     super(); 
    } 
} 

class Test { 
    @Mock private S mockS; 
    new T(); // T's call to super() should call the mock, not the destructive S. 
} 

मैं S में अलग-अलग तरीकों मजाक या केवल मजाक के बारे में सवाल देखा है super() करने के लिए कॉल, और पढ़ा है कि यह असमर्थित है, लेकिन यह स्पष्ट नहीं है कि क्या है या नहीं मैं पूरी सुपर क्लास नकली कर सकते हैं।

मेरे वर्तमान परीक्षणों के साथ, जब मैं S, T पर कॉल करने की कोशिश करता हूं super() वास्तविक कार्यान्वयन को कॉल करता है, न कि नकली।

+0

कैसे करता है अपने नकली कॉल सुपर()? क्या आप एक कोड उदाहरण प्रदान कर सकते हैं? – nansen

+0

@ नैनसेन मैं नकली से 'सुपर()' नहीं बुला रहा हूं, नकली सुपरक्लास है। कृपया मेरे संपादन देखें। –

+1

मुझे वह वर्ग 'एस' पसंद नहीं है। – DerMike

उत्तर

4

इस स्पष्ट सीमा के आसपास काम करने के लिए, मैंने अपना कोड, replacing inheritance with delegation पर प्रतिक्रिया व्यक्त की, और मुझे लगता है कि विरासत वास्तव में आवश्यक नहीं होने के बाद से मैं किसी भी बेहतर डिजाइन के साथ समाप्त हो गया हूं।

नया कोड इस तरह दिखता है। आपको लगता है कि प्रश्न के लिए कोड सरल था, इसलिए वास्तविक वर्गों में अधिक कार्यक्षमता है।

class S { 
    S() { 
     // Format user's hard drive, call 911, and initiate self-destruct 
    } 
} 

class T { 
    T(S s) {} // Now T "has an S" instead of "is an S" 
} 

class Test { 
    @Mock private S mockS; 
    new T(s); // T's call to super() should call the mock, not the destructive S. 
} 

इच्छुक हों, Guice और Android का उपयोग कर, परीक्षण और अधिक इस तरह दिखता है:

class T { 
    T(Activity activity, S s) {} 
} 

class Test { 
    @Mock Activity activity; 
    @Mock S mockS; 
    injector = Guice.createInjector(new AbstractModule() { 
    @Override protected void configure() { 
     bind(Activity.class).toInstance(activity); 
     bind(S.class).toInstance(mockS); 
    }} 
); 
    T t = injector.getInstance(T.class); 
} 
+0

नमस्ते, मैं यहां वर्णित कुछ के समान कुछ हासिल करने की कोशिश कर रहा हूं, मैं इसका परीक्षण कर रहा हूं लेकिन यह BindEverythingElse() पर एक संकलन त्रुटि दिखा रहा है, यह सुनिश्चित नहीं है कि यह वर्ग कहां से है, मैंने guice-2.0 शामिल किया निर्भरता। क्या मुझे कोई अन्य अतिरिक्त निर्भरता जोड़ने की ज़रूरत है या क्या मुझे कुछ याद आ रहा है। धन्यवाद!! – Rishi

+0

@ ऋषि यदि आपके पास कोई अन्य कस्टम बाइंडिंग नहीं है, तो बस उस पंक्ति को खत्म करें। वास्तव में, यह उत्तर के लिए अप्रासंगिक है, इसलिए मैं इसे हटा रहा हूं। –

3

मुझे लगता है कि यह PowerMock के साथ ही संभव है अगर बच्चे पर विधि सुपरक्लास पर विधि से अलग है (यानी, यदि बच्चा उस विधि को ओवरराइड करता है तो आप पैरेंट विधि का नकल नहीं कर सकते हैं)। थोड़ी अधिक जानकारी के लिए, आप the relevant bug report देख सकते हैं।

पावरमोक के लिए, Suppressing Unwanted Behavior page देखें कि यह आपकी आवश्यकताओं के लिए पर्याप्त होगा या नहीं।


बहुत चारों ओर से खुदाई के बाद, मैं इन पेचीदा मामलों के लिए JMockit का उपयोग कर समाप्त हो गया। जेमॉकिट जाने से पहले, मैंने दमन का उपयोग करके सभी जगहों को अपवादों को फेंकने की कोशिश की। अंत में, मुझे कुछ तरीकों को ओवरराइड करने की आवश्यकता थी, न केवल उन्हें दबाएं, इसलिए मैंने इसे छोड़ दिया। एंड्रॉयड मामले के लिए

उदाहरण उपयोग:

पहले, आप अपने सुपर क्लास @MockClass एनोटेशन का उपयोग कर बाहर नकली:

@MockClass(realClass = Activity.class, instantiation = PerMockedInstance) 
public class FakeActivity { 
    public Bundle mSavedInstanceState; 

    @Mock 
    public void $init() {} 

    @Mock 
    public void onCreate(Bundle savedInstanceState) { 
     mSavedInstanceState = savedInstanceState; 
    } 
} 

सक्रिय होने पर, इस वर्ग के $init() साथ Activity के डिफ़ॉल्ट निर्माता का स्थान ले लेगा, और की जगह ऊपर दिए गए के साथ onCreate विधि। WITH एंड्रॉइड, परीक्षण के तहत इकाई गतिविधि से ली गई है (मेरे नमूना कोड में, यह HelloTestActivity है)। परीक्षण वर्ग इस तरह दिखता है:

public class HelloTestActivityTest3 extends AndroidTest { 
    @Tested 
    HelloTestActivity activity; 

    FakeActivity fakeActivity = new FakeActivity(); 

    @Before 
    public void setupMocks() 
    { 
     Mockit.setUpMock(fakeActivity); 
    } 

    @Test 
    public void onCreate_bundle(@Mocked Bundle savedInstanceState) 
    { 
     // Try to access out-of-band information from the fake 
     activity.onCreate(savedInstanceState); 
     assertSame(savedInstanceState, fakeActivity.mSavedInstanceState); 
    } 
} 

कॉल Mockit.setupMock(fakeActivity) नकली की मेरी उदाहरण के साथ सुपर वर्ग बदल देता है। इस उपयोग के साथ, आप अपनी नकली कक्षा की आंतरिक स्थिति तक भी पहुंच सकते हैं। यदि आपको कस्टम कार्यक्षमता के साथ किसी भी तरीके को ओवरराइड करने की आवश्यकता नहीं है, तो आप Mockit कक्षा से उपलब्ध अन्य विधियों का उपयोग कर सकते हैं।

जैसा कि रोगिरियो ने नीचे दी गई टिप्पणियों में बताया है, Activity कक्षा का मज़ाक उड़ा न्यूनतम है। निम्नलिखित कोड यह दर्शाता है।

public class HelloTestActivityTest4 { 
    @Tested 
    HelloTestActivity activity; 

    @Mocked 
    Activity base; 

    @Test 
    public void testOnCreate() throws Exception { 
     // Just make sure "Stub!" exception is not thrown. 
     activity.onCreate(null); 
    } 
} 

घोषणा @Mocked Activity base; सभी तरीकों Activity वर्ग की और उसके सुपर-क्लास (स्थिर initializers को छोड़कर) परीक्षण HelloActivityTest4 में परिभाषित में मज़ाक उड़ाया जा करने के लिए कारण बनता है।

+0

यह मेरी गलतफहमी हो सकती है, लेकिन मैं पूरे सुपरक्लास को मजाक करने के बारे में बात कर रहा हूं, सिर्फ एक विधि नहीं। मेरा संपादन देखें और मुझे बताएं। –

+0

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

+0

क्या हम सभी Android के कारण Powermock का उपयोग कर रहे हैं? :) मैंने पहले से ही 'गतिविधि' का मज़ाक उड़ाया है (मैं उन्हें रोबोगुइस के साथ इंजेक्ट करता हूं और 'mockActivity' उदाहरण के लिए' Activity.class' को बांधता हूं)। इस एसओ पोस्ट के मामले में, मैं 'ArrayAdapter' के विस्तार का परीक्षण कर रहा था और इसे प्रश्न में 'एस' के लिए सामान्यीकृत किया गया था। सफल होने के लिए, मैंने प्रतिनिधिमंडल के साथ विरासत को बदल दिया और फिर इंजेक्शन प्रतिनिधि को मजाक कर दिया। –

1

आप क्या कर सकते हैं अपने सुपरक्लस कन्स्ट्रक्टर में एक गैर-निजी विधि में 'खतरनाक' कोड निकालें, फिर अपने कक्षा टी पर मॉकिटो जासूस का उपयोग करें और उस निकाली गई विधि में व्यवहार को ओवरराइड करें।

यह निश्चित रूप से encapsulation का उल्लंघन करेगा। Guava ऐसे मामलों के लिए VisibleForTesting एनोटेशन प्रदान करता है।

+0

PowerMockito के साथ आपके पास PowerMockito.whenNew (S.class) है .withNoArguments()। फिर वापसी (mockedS); यह तब काम करता है जब आप स्पष्ट रूप से नए एस() को कॉल करते हैं लेकिन सुपर() के साथ नहीं। मेरी हार्ड ड्राइव स्वरूपित;) – nansen

+1

मैंने प्रतिनिधिमंडल के साथ विरासत को बदल दिया और फिर प्रतिनिधि का मज़ाक उड़ाया। –

+0

जो बहुत अच्छा है। +1 – nansen

संबंधित मुद्दे