2012-02-02 13 views
8

एक सार कारखाने कार्यान्वयन को देखते हुए लेता है:इकाई परीक्षण एक सार कारखाने कि मानकों

public class FooFactory : IFooFactory { 
    public IFoo Create(object param1, object param2) { 
     return new Foo(param1, param2); 
    } 
} 

क्या इकाई परीक्षण इस वर्ग के लिए लिखा जाएगा? मैं कैसे सत्यापित कर सकता हूं कि foo के निर्माण के लिए param1 और param2 को अग्रेषित किया गया था? क्या मुझे फू के इन सार्वजनिक गुणों को बनाना है? क्या वह encapsulation तोड़ नहीं होगा? या मुझे इसे एकीकरण परीक्षण में छोड़ देना चाहिए?

+0

यूनिट परीक्षण परीक्षण किए जा रहे घटक पर कार्यात्मक आवश्यकता और अपेक्षाओं पर निर्भर होना चाहिए। मुझे यूनिट परीक्षण का कोई भी मूल्य नहीं दिखता है, जो शेष संदर्भ के बिना कक्षा है। – ivowiblo

+0

@ivowiblo मुझे लगता है कि आप बीडीडी-शैली परीक्षणों के साथ यूनिट परीक्षणों को भ्रमित कर रहे हैं। यदि आप इस इकाई के लिए कोई परीक्षा नहीं लिखते हैं, तो आप कैसे जानते हैं कि यह काम करता है? –

+0

इकाई परीक्षण करें, लेकिन आप परीक्षण करेंगे क्या? उस इकाई के लिए उम्मीद कौन सा है? मैंने कहा कि मुझे किसी और चीज के बिना उस वर्ग के यूनिट टेस्ट करने का मूल्य नहीं दिख रहा है। इकाई परीक्षण करने के कारण यूनिट परीक्षण करना बिल्कुल समझ में नहीं आता है। परीक्षण (इकाइयों, व्यवहार, पूर्ण कार्यक्षमताओं, जो भी आप चाहते हैं) हमेशा उम्मीदों और आवश्यकताओं से प्रेरित किया जाना चाहिए। यदि नहीं, तो यह सिर्फ स्नोबिज्म है (यदि वह शब्द मौजूद है)। – ivowiblo

उत्तर

11

यहां बताया गया है मैं (xUnit.net के साथ) इस तरह के एक कारखाने के लिए इकाई परीक्षण के एक जोड़े में से एक ने लिखा है:

[Fact] 
public void CreateReturnsInstanceWithCorrectParam1() 
{ 
    var sut = new FooFactory(); 
    var expected = new object(); 
    var actual = sut.Create(expected, new object()); 
    var concrete = Assert.IsAssignableFrom<Foo>(actual); 
    Assert.Equal(expected, concrete.Object1); 
} 

यह कैप्सूलीकरण तोड़ करता है? हाँ और नहीं ... थोड़ा सा। Encapsulation न केवल डेटा छिपाने के बारे में है - अधिक महत्वपूर्ण बात यह है कि यह लगभग protecting the invariants of objects है।

मान लेते हैं कि फू इस सार्वजनिक एपीआई को उजागर करता है:

public class Foo : IFoo 
{ 
    public Foo(object param1, object param2); 

    public void MethodDefinedByInterface(); 

    public object Object1 { get; } 
} 

Object1 संपत्ति थोड़ा Law of Demeter का उल्लंघन है, ऐसा नहीं गड़बड़ वर्ग के अपरिवर्तनशीलताओं साथ है क्योंकि यह केवल पढ़ने के लिए है नहीं करता है।

इसके अलावा, Object1 संपत्ति ठोस फू वर्ग का हिस्सा है - नहीं IFoo इंटरफ़ेस:

public interface IFoo 
{ 
    void MethodDefinedByInterface(); 
} 

एक बार जब आप महसूस करते हैं कि एक शिथिल युग्मित एपीआई, concrete members are implementation details में, इस तरह के ठोस-केवल केवल पढ़ने के गुण होते हैं encapsulation पर बहुत कम प्रभाव। इसके बारे में इस तरह सोचें:

सार्वजनिक फू निर्माता भी ठोस फू वर्ग के एपीआई का एक हिस्सा है, इसलिए सिर्फ सार्वजनिक एपीआई निरीक्षण के द्वारा, हम सीखते हैं कि param1 और param2 वर्ग का हिस्सा हैं। एक अर्थ में, यह पहले से ही 'encapsulation तोड़ता है', इसलिए कंक्रीट वर्ग पर केवल-पढ़ने वाले गुणों के रूप में उपलब्ध प्रत्येक पैरामीटर को बहुत अधिक नहीं बदलता है।

इस तरह के गुण लाभ प्रदान करते हैं कि अब हम कारखाने द्वारा लौटाए गए फू क्लास के संरचनात्मक आकार का परीक्षण कर सकते हैं।

व्यवहारिक इकाई परीक्षणों के एक सेट को दोहराने से कहीं अधिक आसान है, हमें यह मानना ​​चाहिए कि पहले से ही कंक्रीट फू क्लास को कवर किया गया है। यह लगभग तार्किक सबूत की तरह है:

  1. कंक्रीट फू क्लास के परीक्षणों से हम जानते हैं कि यह अपने कन्स्ट्रक्टर पैरामीटर के साथ सही तरीके से उपयोग/इंटरैक्ट करता है।
  2. इन परीक्षणों से हम यह भी जानते हैं कि निर्माता पैरामीटर केवल पढ़ने-योग्य संपत्ति के रूप में सामने आया है।
  3. FooFactory के एक परीक्षण से हम जानते हैं कि यह कंक्रीट फू क्लास का एक उदाहरण देता है।
  4. इसके अलावा, हम निर्माण विधि के परीक्षणों से जानते हैं कि इसके पैरामीटर फ़ू कन्स्ट्रक्टर को सही ढंग से पास किए गए हैं।
  5. Q.E.D.
+0

हां, समझ में आता है। मुझे इंटरफ़ेस और कंक्रीट क्लास के सार्वजनिक एपीआई के बीच अंतर करने का विचार पसंद है। – JontyMC

+0

अज्ञात डाउनवोट क्यों? –

0

आप FooFactory को एक सामान्य वर्ग बना सकते हैं जो फू को पैरामीटर के रूप में अपेक्षा करता है, और यह निर्दिष्ट करता है कि यह नकली हो। कॉलिंग फैक्ट्री। क्रिएट (...) फिर नकली का एक उदाहरण बनाता है, और फिर आप पुष्टि कर सकते हैं कि नकली ने आपके द्वारा अपेक्षित तर्क प्राप्त किए हैं।

+2

प्रिय गोडेल संख्या। यह एक कार्यान्वयन विस्तार का परीक्षण कर रहा है। – jason

+0

@ जेसन: इससे भी बदतर ... यह उस फैक्ट्री के लिए ऑब्जेक्ट उत्पन्न करने के लिए फैक्ट्री बनाने का सवाल उठाता है, लेकिन यदि जोंटीएमएमसी पूछता है ... – Arafangion

0

यह इस बात पर निर्भर करता है कि 2 इनपुट ऑब्जेक्ट्स के साथ फू क्या करता है। कुछ ऐसा जांचें जो फू उनके साथ करता है जिसे आसानी से पूछताछ की जा सकती है। उदाहरण के लिए, यदि वस्तुओं पर (गेटर्स या सेटर्स समेत) विधियों को बुलाया जाता है, तो उन मॉक्स या स्टब्स प्रदान करें जिन्हें आप सत्यापित कर सकते हैं जिन्हें अपेक्षित चीजें कहा जाता है। यदि आईफू पर कुछ ऐसा है जिसका परीक्षण किया जा सकता है, तो आप सृजन के बाद परीक्षण करने के लिए अपने नकली वस्तुओं के माध्यम से ज्ञात मूल्यों को पारित कर सकते हैं। वस्तुओं को स्वयं को सत्यापित करने के लिए सार्वजनिक रूप से उपलब्ध होने की आवश्यकता नहीं है कि आप उन्हें पारित कर चुके हैं।

मैं यह भी सत्यापित कर सकता हूं कि अपेक्षित प्रकार (फू) वापस आ गया है, इस पर निर्भर करता है कि अन्य व्यवहार परीक्षण IFoo कार्यान्वयन के बीच अंतर पर निर्भर करते हैं या नहीं।

यदि कोई त्रुटि स्थितियां हैं जो परिणाम दे सकती हैं, तो मैं उनको मजबूर करने की कोशिश करता हूं, यदि आप किसी भी या दोनों वस्तुओं के लिए शून्य में गुजरते हैं तो क्या होता है। फू का अलग-अलग परीक्षण किया जाएगा, इसलिए आप एक FooFactory परीक्षण के दौरान मान सकते हैं कि फू करता है कि यह क्या करना चाहिए।

+0

आप रिटर्न प्रकार का परीक्षण करेंगे? पृथ्वी पर क्या है कि आप खरीद रहे हैं? आपने इन सभी अवशेषों को स्थापित कर लिया है और अब आप एक परीक्षण लिखने जा रहे हैं जैसे ही आप कार्यान्वयन विवरण बदलते हैं। ओह। – jason

+0

@ जेसन यदि मैं कई कारखानों के लिए परीक्षण लिखने जा रहा हूं कि प्रत्येक एक आईएफयू कार्यान्वयन बनाता है, तो मैं जांचता हूं कि प्रत्येक ठोस प्रकार की अपेक्षा करता है जो मुझे उम्मीद है। मैं ऐसे फैक्ट्री का परीक्षण करने की आवश्यकता पर सवाल करता हूं जो नए कॉल के रूप में बहुत कम करता है, लेकिन जो पूछा गया था उसके दायरे में ... –

+0

नहीं। कारखाने का व्यवहार करने वाला यह काम नहीं कर सकता है (वापसी का प्रकार 'IFoo' है) इसका परीक्षण नहीं किया जाना चाहिए। – jason

0

कारखाने आमतौर पर यूनिट-परीक्षण नहीं होते हैं, कम से कम मेरे अनुभव के अनुसार - यूनिट परीक्षण में में बहुत अधिक मूल्य नहीं है। क्योंकि यह उस इंटरफ़ेस-कार्यान्वयन मानचित्रण का कार्यान्वयन है इसलिए यह ठोस कार्यान्वयन को संदर्भित करता है। जैसे, मजाक Foo चाहे वह उन मानकों दूसरी ओर में।

पारित कर दिया प्राप्त करता है की जाँच करने के लिए संभव नहीं है, आम तौर पर डि कंटेनर इसलिए यदि आप एक का उपयोग कर रहे कारखानों के रूप में काम करते हैं, आप एक कारखाने की जरूरत नहीं होगी।

+0

सार कारखानों की आवश्यकता होती है जब एक निर्भरता केवल रन-टाइम पर ज्ञात पैरामीटर पर निर्भर करती है या जीवनकाल उपभोक्ता की तुलना में कम होता है: http://stackoverflow.com/questions/1993397/abstract-factory-pattern-on-top- ऑफ-आईओसी – JontyMC

+0

अधिकांश डी ढांचे रनटाइम पर पैरामीटर के गुजरने के लिए करेंगे। वे आजीवन प्रबंधन भी कर सकते हैं। – Aliostad

2

ठीक है, संभवतः उन पैरामीटर लौटाए गए IFoo के बारे में कुछ सच है। लौटाए गए उदाहरण के बारे में सच होने के लिए परीक्षण करें।

+0

क्या इसका मतलब यह नहीं होगा कि आपको आईएफयू के आंतरिक प्रश्नों के बारे में जानना होगा? – JontyMC

+0

नहीं। आप कुछ मानदंडों को प्राप्त करने के लिए, उन मानकों में किसी कारण से गुज़र रहे हैं। वह व्यवहार क्या है? इसके लिए परीक्षण करें। 'FooFactory.Create' के लिए spec कुछ ऐसा कहना चाहिए "ऐसा ऑब्जेक्ट बनाता है जो' IFoo 'लागू करता है जैसे कि' पी (param1, param2) 'जहां' पी' 'param1' और' param2' पर निर्भर एक अनुमान है।" परीक्षण करें कि 'पी (param1, param2) 'लौटाई गई वस्तु के लिए सच है! – jason

+0

तो ... यह मानते हुए कि फू गैर-तुच्छ है और पहले से ही एन परीक्षणों द्वारा कवर किया गया है, आपको अनिवार्य रूप से एन नए, लगभग समान परीक्षणों को जांचने की आवश्यकता होगी ताकि परीक्षण किया जा सके कि लौटा हुआ Foo उदाहरण का व्यवहार निर्माण के इनपुट के अनुरूप है तरीका। ऐसा लगता है कि आप अप्रत्यक्ष रूप से परीक्षणों को जोड़ना चाहते हैं। रखरखाव के मुद्दों का पालन करेंगे। –