2010-05-19 10 views
41

इस बारे में सोचने का एक तरीका यह है: यदि हम कोड के डिज़ाइन की परवाह करते हैं तो EasyMock बेहतर विकल्प है क्योंकि यह उम्मीदों की अवधारणा से आपको प्रतिक्रिया देता है।EasyMock बनाम Mockito: डिजाइन बनाम रखरखाव?

यदि हम परीक्षणों की रखरखाव (पढ़ने के लिए आसान, लिखना और कम भंगुर परीक्षण करना चाहते हैं जो परिवर्तन से ज्यादा प्रभावित नहीं होते हैं), तो मॉकिटो बेहतर विकल्प लगता है।

मेरे प्रश्न हैं:

  • आप बड़े पैमाने पर परियोजनाओं में EasyMock का इस्तेमाल किया है, तो आप पाते हैं कि आपके परीक्षण रेख करने में कठिन हैं?
  • मोकिटो की सीमाएं क्या हैं (एंडो परीक्षण के अलावा)?

उत्तर

26

मैं एक आसान मैक डेवलपर हूं इसलिए थोड़ा सा आंशिक लेकिन निश्चित रूप से मैंने बड़े पैमाने पर परियोजनाओं पर EasyMock का उपयोग किया है।

मेरी राय यह है कि EasyMock परीक्षण वास्तव में थोड़ी देर में टूट जाएंगे। EasyMock आपको अपनी अपेक्षा की पूरी रिकॉर्डिंग करने के लिए मजबूर करता है। इसके लिए कुछ अनुशासन की आवश्यकता है। आपको वास्तव में रिकॉर्ड करना चाहिए कि अपेक्षित परीक्षण विधि को वर्तमान में क्या चाहिए। उदाहरण के लिए, यदि इससे कोई फर्क नहीं पड़ता कि नकली पर विधि को कितनी बार बुलाया जाता है, तो andStubReturn का उपयोग करने से डरो मत। इसके अलावा, अगर आपको पैरामीटर की परवाह नहीं है, तो anyObject() और इसी तरह का उपयोग करें। टीडीडी में सोचने से उस पर मदद मिल सकती है।

मेरा विश्लेषण यह है कि EasyMock परीक्षण अधिक बार टूट जाएंगे, लेकिन मॉकिटो लोग तब नहीं करेंगे जब आप उन्हें चाहते हैं। मैं तोड़ने के लिए अपने परीक्षण पसंद करते हैं। कम से कम मुझे पता है कि मेरे विकास के प्रभाव क्या थे। यह निश्चित रूप से, मेरा व्यक्तिगत दृष्टिकोण है।

+1

हाँ, मैं सोच कर दिया गया है एक ही: Mockito (और Unitils नकली, एक ऐसी ही मजाक एपीआई) के साथ यह बहुत परीक्षण है कि खुशी से जब वे नहीं करना चाहिए पारित करने के लिए जारी रखने के लिए लिखने के लिए आसान है। मुझे संदेह है कि यह मुख्य कारण हो सकता है कि मॉकिटो-जैसी एपीआई, जो अत्यधिक "ढीले" परीक्षणों के निर्माण को सुविधाजनक बनाती है, को अक्सर "आसान" माना जाता है। –

+3

मुझे एक उदाहरण देखने में दिलचस्पी होगी जो इन 2 दृष्टिकोणों से विरोधाभास करता है ... – Armand

7

मुझे नहीं लगता कि आपको इसके बारे में बहुत चिंतित होना चाहिए। Easymock और Mockito दोनों को 'सख्त' या 'अच्छा' होने के लिए कॉन्फ़िगर किया जा सकता है, केवल अंतर यह है कि डिफ़ॉल्ट रूप से Easymock सख्त वेरास मॉकिटो अच्छा है।

सभी परीक्षणों के साथ कोई कठोर और तेज़ नियम नहीं है, तो आपको रखरखाव के खिलाफ परीक्षण आत्मविश्वास को संतुलित करने की आवश्यकता है। मुझे आमतौर पर कुछ कार्यात्मक या तकनीकी क्षेत्र मिलते हैं जो उच्च स्तर की आत्मविश्वास की मांग करते हैं जिसके लिए मैं 'सख्त' मोक्स का उपयोग करूंगा। उदाहरण के लिए हम शायद डेबिट अकाउंट() विधि को एक से अधिक बार नहीं बुलाएंगे! हालांकि ऐसे अन्य मामले हैं जिनमें नकली वास्तव में एक स्टब से थोड़ा अधिक है ताकि हम कोड के असली 'मांस' का परीक्षण कर सकें।

मॉकिटो के जीवन के शुरुआती दिनों में एपीआई संगतता एक समस्या थी लेकिन अधिक टूल अब ढांचे का समर्थन करते हैं। Powermock (एक व्यक्तिगत पसंदीदा) अब एक mockito विस्तार

42

है अगर हम कोड के डिजाइन के बारे में परवाह तो Easymock यह के रूप में बेहतर विकल्प प्रतिक्रिया आप के लिए उम्मीदों

दिलचस्प की अपनी अवधारणा से देता है । मैंने पाया कि 'अपेक्षाओं की अवधारणा' कई देवताओं को अधिक 0xकेवल अप्रत्याशित MethodCall समस्या को पूरा करने के लिए परीक्षणों में अधिक अपेक्षाओं को डालती है। यह डिजाइन को कैसे प्रभावित करता है?

जब आप कोड बदलते हैं तो परीक्षण तोड़ना नहीं चाहिए। जब फीचर काम करना बंद कर देता है तो परीक्षण तोड़ना चाहिए।यदि कोई कोड बदलता है तो ब्रेक करने के लिए परीक्षण पसंद करते हैं, तो मैं एक परीक्षा लिखने का सुझाव देता हूं जो जावा फ़ाइल के एमडी 5 चेकसम को दावा करता है :)

94

मैं इन ढांचे की परीक्षण पठनीयता, आकार या परीक्षण तकनीकों के बारे में बहस नहीं करूंगा, मेरा मानना ​​है कि वे बराबर हैं, लेकिन एक साधारण उदाहरण पर मैं आपको अंतर दिखाऊंगा।

को देखते हुए: हम एक वर्ग जो कहीं कुछ संचय के लिए जिम्मेदार है:

public class Service { 

    public static final String PATH = "path"; 
    public static final String NAME = "name"; 
    public static final String CONTENT = "content"; 
    private FileDao dao; 

    public void doSomething() { 
     dao.store(PATH, NAME, IOUtils.toInputStream(CONTENT)); 
    } 

    public void setDao(FileDao dao) { 
     this.dao = dao; 
    } 
} 

और हम इसे परीक्षण करना चाहते हैं:

Mockito:

public class ServiceMockitoTest { 

    private Service service; 

    @Mock 
    private FileDao dao; 

    @Before 
    public void setUp() { 
     MockitoAnnotations.initMocks(this); 
     service = new Service(); 
     service.setDao(dao); 
    } 

    @Test 
    public void testDoSomething() throws Exception { 
     // given 
     // when 
     service.doSomething(); 
     // then 
     ArgumentCaptor<InputStream> captor = ArgumentCaptor.forClass(InputStream.class); 
     Mockito.verify(dao, times(1)).store(eq(Service.PATH), eq(Service.NAME), captor.capture()); 
     assertThat(Service.CONTENT, is(IOUtils.toString(captor.getValue()))); 
    } 
} 

EasyMock:

public class ServiceEasyMockTest { 
    private Service service; 
    private FileDao dao; 

    @Before 
    public void setUp() { 
     dao = EasyMock.createNiceMock(FileDao.class); 
     service = new Service(); 
     service.setDao(dao); 
    } 

    @Test 
    public void testDoSomething() throws Exception { 
     // given 
     Capture<InputStream> captured = new Capture<InputStream>(); 
     dao.store(eq(Service.PATH), eq(Service.NAME), capture(captured)); 
     replay(dao); 
     // when 
     service.doSomething(); 
     // then 
     assertThat(Service.CONTENT, is(IOUtils.toString(captured.getValue()))); 
     verify(dao); 
    } 
} 

जैसा कि आप देख सकते हैं कि दोनों टेस्ट काफी समान हैं और उनमें से दोनों गुजर रहे हैं। अब, कल्पना करें कि किसी और ने सेवा कार्यान्वयन और परीक्षण चलाने की कोशिश की है।

नया सेवा कार्यान्वयन:

dao.store(PATH + separator, NAME, IOUtils.toInputStream(CONTENT)); 

विभाजक पथ के अंत लगातार

पर जोड़ा गया है कैसे परीक्षण परिणाम अभी कैसे दिखेंगे? सभी दोनों परीक्षणों के पहले असफल हो जायेगी, लेकिन अलग त्रुटि संदेश के साथ:

EasyMock:

java.lang.AssertionError: Nothing captured yet 
    at org.easymock.Capture.getValue(Capture.java:78) 
    at ServiceEasyMockTest.testDoSomething(ServiceEasyMockTest.java:36) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 

Mockito:

Argument(s) are different! Wanted: 
dao.store(
    "path", 
    "name", 
    <Capturing argument> 
); 
-> at ServiceMockitoTest.testDoSomething(ServiceMockitoTest.java:34) 
Actual invocation has different arguments: 
dao.store(
    "path\", 
    "name", 
    [email protected] 
); 
-> at Service.doSomething(Service.java:13) 

EasyMock परीक्षा में क्या हुआ, क्यों परिणाम पर कब्जा कर लिया नहीं किया गया था? क्या स्टोर विधि निष्पादित नहीं की गई थी, लेकिन एक मिनट प्रतीक्षा करें, यह क्यों था, EasyMock हमसे क्यों झूठ बोलता है?

ऐसा इसलिए है क्योंकि EasyMock एक पंक्ति में दो जिम्मेदारियों को मिलाकर - स्टबिंग और सत्यापन। यही कारण है कि जब कुछ गलत होता है तो यह समझना मुश्किल होता है कि कौन सा हिस्सा विफलता पैदा कर रहा है।

बेशक आप मुझे बता सकते हैं - बस परीक्षण को बदलें और दावा से पहले सत्यापित करें। वाह, क्या आप गंभीर हैं, डेवलपर्स को फ्रेमवर्क का मज़ाक उड़ाकर कुछ जादू आदेश को ध्यान में रखना चाहिए?

वैसे, यह मदद नहीं करेगा:

java.lang.AssertionError: 
    Expectation failure on verify: 
    store("path", "name", capture(Nothing captured yet)): expected: 1, actual: 0 
    at org.easymock.internal.MocksControl.verify(MocksControl.java:111) 
    at org.easymock.classextension.EasyMock.verify(EasyMock.java:211) 

फिर भी, यह कह रहा है मुझे लगता है कि विधि क्रियान्वित नहीं था, लेकिन यह था केवल एक और मानकों के साथ।

क्यों मॉकिटो बेहतर है? यह ढांचा एक ही स्थान पर दो जिम्मेदारियों को मिश्रित नहीं करता है और जब आपके परीक्षण विफल हो जाएंगे, तो आप आसानी से समझेंगे क्यों।

+0

मुझे पहले मॉकिटो की कोशिश करने पर बेचा जाता है। टेस्ट रखरखाव रास्ते में हो रही नकली ढांचे के साथ पर्याप्त गन्दा है। – Gary

+0

मुझे एहसास है कि यह पुराना है ... लेकिन, यह आप EasyMock पर यहां सत्यापित और स्टबिंग प्रक्रियाओं को मिश्रित कर रहे हैं। सत्यापन से पहले दावा करना बुरा व्यवहार है- इस प्रकार आप वास्तव में 'assertThat' कॉल को हटा सकते हैं क्योंकि सत्यापन आपके लिए इसे उठाएगा: "FileStore.dao (" path "," name ", कैप्चर (अभी तक कैप्चर नहीं किया गया)): अपेक्षित 1, वास्तविक: 0 "। मैं स्वीकार करूंगा कि मॉकिटो संदेश यहां स्पष्ट है लेकिन यह EasyMock के बारे में किसी के निर्णय को प्रभावित करने के लिए इस बेहद विशिष्ट उदाहरण में पर्याप्त नहीं है! –

+0

मुझे यकीन नहीं है कि मैंने इज़ीमॉक के लिए यहां कुछ कैसे मिलाया, इस तरह यह काम करता है, इसलिए यदि आपके पास एक अच्छा काउंटर उदाहरण है तो मुझे यह देखकर खुशी होगी। मुझे लगता है कि यह व्यक्तिगत राय का मामला गीला है या नहीं, यह उदाहरण इन ढांचे पर निर्णय को प्रभावित करने के लिए पर्याप्त है और मुझे खुशी है कि कई लोगों को यह मूल्यवान लगता है। –

5

मैं ईमानदार होने के लिए मॉकिटो पसंद करता हूं। यूनिटिल के साथ EasyMock का उपयोग कर रहा है और दोनों के संयोजन का परिणाम अक्सर IllegalArgumentException जैसे अपवादों में होता है: इंटरफ़ेस के साथ-साथ MissingBehaviorExceptions भी नहीं। दोनों मामलों में हालांकि कोड और टेस्ट कोड पूरी तरह ठीक हैं। ऐसा प्रतीत होता है कि MissingBehaviorException इस तथ्य के कारण था कि createMock (classextentions !! का उपयोग करके बनाई गई मॉक ऑब्जेक्ट्स) ने इस त्रुटि का उत्पादन किया था। @Mock का उपयोग करते समय यह काम किया!मुझे इस तरह के भ्रामक व्यवहार पसंद नहीं हैं और मेरे लिए यह एक स्पष्ट संकेत है कि इसके डेवलपर्स नहीं जानते कि वे क्या कर रहे हैं। एक अच्छा ढांचा हमेशा उपयोग करना आसान और अस्पष्ट नहीं होना चाहिए। IllegalArgumentException भी EasyMock internals के कुछ मिश्रण के कारण था। इसके अलावा, रिकॉर्डिंग वह नहीं है जो मैं करना चाहता हूं। मैं परीक्षण करना चाहता हूं कि मेरा कोड अपवाद फेंकता है या नहीं और यह अपेक्षित परिणाम देता है। कोड कवरेज के संयोजन में यह मेरे लिए सही उपकरण है। मैं नहीं चाहता कि जब भी मैं पिछले पंक्ति के ऊपर या नीचे कोड डालूं तो मेरे परीक्षण तोड़ने के लिए क्योंकि यह प्रदर्शन में सुधार करता है या नहीं। मॉकिटो के साथ यह कोई समस्या नहीं है। EasyMock के साथ, परिणाम परिणाम विफल होने के बावजूद परीक्षण विफल हो जाएंगे। वह बुरा है। यह समय, इस तरह पैसे खर्च करता है। आप अपेक्षित व्यवहार के लिए परीक्षण करना चाहते हैं। क्या आप वाकई चीजों के आदेश की परवाह करते हैं? मुझे लगता है कि आप दुर्लभ मौकों पर हो सकता है। फिर Easymock का प्रयोग करें। दूसरे मामले में, मुझे लगता है कि आप अपने परीक्षण लिखने के लिए मॉकिटो का उपयोग करके काफी कम समय व्यतीत करेंगे।

तरह का संबंध लॉरेंस

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