2009-06-30 15 views
31

के रूप में एक ठोस वर्ग है, इसलिए मेरे पास एक कारखाना वर्ग है और मैं यूनिट परीक्षणों को करने के लिए काम करने की कोशिश कर रहा हूं। इस question से मैं सत्यापित कर सकता हूं कि इंटरफ़ेस लौटा एक विशेष ठोस प्रकार है जो मैं उम्मीद करता हूं।यूनिट परीक्षण कारखाने के तरीके जिनके पास रिटर्न प्रकार

कारखाने ठोस प्रकार लौट रहे हैं (क्योंकि फिलहाल कोई आवश्यकता नहीं है - इंटरफेस का उपयोग करने के लिए) की जांच करनी चाहिए?

[Test] 
public void CreateSomeClassWithDependencies() 
{ 
    // m_factory is instantiated in the SetUp method 
    var someClass = m_factory.CreateSomeClassWithDependencies(); 

    Assert.IsNotNull(someClass); 
} 

इस के साथ समस्या यह है कि कुछ हद तक Assert.IsNotNull बेमानी लगता है: वर्तमान में मैं निम्नलिखित की तरह कुछ कर रहा हूँ।

इसके अलावा, मेरे कारखाने विधि उस विशेष वर्ग की निर्भरता इतनी तरह की स्थापना की जा सकती है:

public SomeClass CreateSomeClassWithDependencies() 
{ 
    return new SomeClass(CreateADependency(), CreateAnotherDependency(), 
         CreateAThirdDependency()); 
} 

और मुझे यकीन है कि मेरे कारखाने विधि सही ढंग से इन सभी निर्भरता सेट बनाना चाहते हैं। क्या ऐसा करने का कोई और तरीका नहीं है, तो उन निर्भरताओं को public/internal गुणों को बनाने के लिए जिन्हें मैं इकाई परीक्षण में जांचता हूं? (मैं परीक्षण के अनुरूप परीक्षण विषयों को संशोधित करने का एक बड़ा प्रशंसक नहीं हूं)

संपादित करें: रॉबर्ट हार्वे के प्रश्न के जवाब में, मैं अपने यूनिट परीक्षण ढांचे के रूप में न्यूटिट का उपयोग कर रहा हूं (लेकिन मैंने सोचा नहीं होगा इससे बहुत अंतर आएगा)

+0

आप किस परीक्षण ढांचे का उपयोग कर रहे हैं? –

+0

कुछ परीक्षण ढांचे की आवश्यकता है कि आपकी कक्षाएं आभासी हों ताकि परीक्षण ढांचा उन्हें प्राप्त कर सके। कुछ नहीं करते हैं। बडा फर्क। –

उत्तर

32

अक्सर, सार्वजनिक संपत्तियों के निर्माण में कुछ भी गलत नहीं है जिसका उपयोग राज्य-आधारित परीक्षण के लिए किया जा सकता है। हां: यह कोड है जिसे आपने परीक्षण परिदृश्य को सक्षम करने के लिए बनाया है, लेकिन क्या यह आपके एपीआई को चोट पहुंचाता है? क्या यह कल्पना की जा सकती है कि अन्य क्लाइंट एक ही संपत्ति को बाद में उपयोगी पाएंगे?

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

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

इसके अलावा, मैं दूसरे नादर के जवाब :)

+1

+1। निर्भरताओं का पर्दाफाश करने के लिए गुणों का उपयोग करने से दोनों निर्भरताओं को कॉन्फ़िगर करने में मदद मिलती है, और उन्हें स्पष्ट बना दिया जाता है। दोनों अच्छी चीजें हैं। –

+0

@nader: अच्छी तरह से रखो - यही वह था जो मैं कहने की कोशिश कर रहा था :) –

+0

+1 इसलिए अक्सर मुझे कुछ सार्वजनिक संपत्ति बनाने की ज़रूरत होती है ताकि मैं केवल यूनिट परीक्षण कर सकूं ताकि मुझे यह पता चल सके कि मुझे कोड और अन्य लोगों में बाद में इसकी आवश्यकता है इसकी भी आवश्यकता है। – uriDium

3

हम जो करते हैं वह कारखानों के साथ निर्भरता पैदा करता है, और परीक्षण के चलते वास्तविक लोगों के लिए नकली कारखानों को प्रतिस्थापित करने के लिए हम निर्भरता इंजेक्शन ढांचे का उपयोग करते हैं। फिर हमने उन नकली कारखानों पर उचित अपेक्षाएं स्थापित कीं।

3

आप हमेशा प्रतिबिंब के साथ सामान की जांच कर सकते हैं। केवल यूनिट परीक्षणों के लिए कुछ बेनकाब करने की आवश्यकता नहीं है। मुझे यह बहुत दुर्लभ लगता है कि मुझे प्रतिबिंब के साथ पहुंचने की जरूरत है और यह खराब डिजाइन का संकेत हो सकता है।

अपना नमूना कोड देख रहे हैं, हां, आपके कारखाने को डिज़ाइन करने के तरीके के आधार पर आर्ट नट अनावश्यक लगता है, कुछ अपवाद के विपरीत कारखाने से शून्य वस्तुओं को वापस कर देंगे।

23

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

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

यदि आपकी भाषा आपकी निर्भरताओं के लिए इसका समर्थन करती है, तो आप प्रतिबिंब का उपयोग कर सकते हैं। यह हमेशा बनाए रखने के लिए सबसे आसान नहीं है, और आपके परीक्षणों को आपके कार्यान्वयन के लिए बहुत कसकर जोड़ता है। आपको यह तय करना होगा कि क्या यह स्वीकार्य है या नहीं। यह दृष्टिकोण बहुत भंगुर हो जाता है।

लेकिन आप वास्तव में रचनाओं को कहने के तरीके से अलग-अलग वर्गों का निर्माण करने की कोशिश कर रहे हैं। आप उस तरह की लचीलापन प्राप्त करने के लिए डीआई फ्रेमवर्क का उपयोग करने के साथ बेहतर हो सकते हैं।

new द्वारा आपके सभी प्रकारों को ऊपर उठाने के लिए, आप स्वयं को कई सीम नहीं देते हैं (एक सीम एक ऐसी जगह है जहां आप उस स्थान पर संपादन किए बिना अपने प्रोग्राम में व्यवहार को बदल सकते हैं) के साथ काम करने के लिए।

उदाहरण के साथ, जैसा कि आप इसे देते हैं, आप कारखाने से एक कक्षा प्राप्त कर सकते हैं।फिर ओवरराइड/नकली CreateADependency(), CreateAnotherDependency() और CreateAThirdDependency()। अब जब आप CreateSomeClassWithDependencies() पर कॉल करते हैं, तो आप समझ सक्षम कर सकते हैं कि सही निर्भरताएं बनाई गई थी या नहीं।

नोट: "सीम" की परिभाषा माइकल फेदर की पुस्तक "लीगेसी कोड के साथ प्रभावी ढंग से कार्य करना" से आती है। इसमें अवांछित कोड में टेस्टेबिलिटी जोड़ने के लिए कई तकनीकों के उदाहरण शामिल हैं। आप इसे बहुत उपयोगी पा सकते हैं।

+1

मुझे जवाब पसंद है और यह पुस्तक एक ईश्वर भेजती है यदि आपको किसी भी परीक्षा के बिना विरासत या विरासत (.net 1.1) कोड के साथ सौदा करना है। यह भी अच्छा है कि आप एक टीम में हैं जहां इकाई परीक्षण पहले नहीं किया गया था और आपके पास बहुत सारे ब्राउनफील्ड कोड हैं जिन्हें आप यूनिट परीक्षण करना चाहते हैं कि पुस्तक बहुत उपयोगी है। "हमारे डिजाइन को ड्राइव करने दें" के लिए – ElvisLives

0

मैं समझता हूँ कि यह आप परीक्षण करने के लिए है कि निर्भरता सही ढंग से बनाया गया है और नया उदाहरण के लिए पारित कर रहे हैं करना चाहते हैं?

@Test 
public void CreateSomeClassWithDependencies() 
{ 
    dependencyFactory = context.mock(DependencyFactory.class); 
    classAFactory = context.mock(ClassAFactory.class); 

    myDependency0 = context.mock(MyDependency0.class); 
    myDependency1 = context.mock(MyDependency1.class); 
    myDependency2 = context.mock(MyDependency2.class); 
    myClassA = context.mock(ClassA.class); 

    context.checking(new Expectations(){{ 
     oneOf(dependencyFactory).createDependency0(); will(returnValue(myDependency0)); 
     oneOf(dependencyFactory).createDependency1(); will(returnValue(myDependency1)); 
     oneOf(dependencyFactory).createDependency2(); will(returnValue(myDependency2)); 

     oneOf(classAFactory).createClassA(myDependency0, myDependency1, myDependency2); 
     will(returnValue(myClassA)); 
    }}); 

    builder = new ClassABuilder(dependencyFactory, classAFactory); 

    assertThat(builder.make(), equalTo(myClassA)); 
} 

(यदि आप ClassA नकली नहीं कर सकते हैं आप एक प्रदान कर सकते हैं:

अगर मैं गूगल guice की तरह एक ढांचे का उपयोग करने में सक्षम नहीं था, मैं शायद यह कुछ इस तरह (यहाँ JMock और Hamcrest का प्रयोग करके) करना होगा नए का उपयोग कर myClassA में गैर-नकली संस्करण)

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