2011-07-12 10 views
12

मैं अपने आवेदन सेवा परत में तरीकों कि इस तरह की बातें कर रहे हैं का एक समूह मिल गया है:आवेदन सेवा परत: यूनिट टेस्ट, एकीकरण टेस्ट, या दोनों?

public void Execute(PlaceOrderOnHoldCommand command) 
{ 
    var order = _repository.Load(command.OrderId); 
    order.PlaceOnHold(); 
    _repository.Save(order); 
} 

और वर्तमान में, मैं इस तरह इकाई परीक्षण का एक समूह है:

[Test] 
public void PlaceOrderOnHold_LoadsOrderFromRepository() 
{ 
    var repository = new Mock<IOrderRepository>(); 
    const int orderId = 1; 
    var order = new Mock<IOrder>(); 
    repository.Setup(r => r.Load(orderId)).Returns(order.Object); 

    var command = new PlaceOrderOnHoldCommand(orderId); 
    var service = new OrderService(repository.Object); 
    service.Execute(command); 

    repository.Verify(r => r.Load(It.Is<int>(x => x == orderId)), Times.Exactly(1)); 
} 

[Test] 
public void PlaceOrderOnHold_CallsPlaceOnHold() 
{ 
      /* blah blah */ 
} 

[Test] 
public void PlaceOrderOnHold_SavesOrderToRepository() 
{ 
      /* blah blah */ 
} 

ऐसा लगता है कि ये यूनिट परीक्षण उस मूल्य को जोड़ता है जो प्रयास के लायक है। मुझे पूरा यकीन है कि आवेदन सेवा परत एकीकरण परीक्षण होना चाहिए, यद्यपि।

क्या आवेदन सेवा परत को इस स्तर पर ग्रैन्युलरिटी के स्तर पर परीक्षण किया जाना चाहिए, या एकीकरण परीक्षण पर्याप्त हैं?

उत्तर

8

बिल्कुल: यह बहस योग्य है! यह वास्तव में अच्छा है कि आप जो मूल्य लाएंगे, उसके मुकाबले आपके परीक्षण को लिखने और बनाए रखने के खर्च/प्रयास का वजन कर रहे हैं - और यह वही विचार है जो आपको लिखने वाले प्रत्येक परीक्षण के लिए करना चाहिए। अक्सर मैं परीक्षण के लिए लिखे गए परीक्षण देखता हूं और इस प्रकार कोड बेस पर केवल गिट्टी जोड़ता हूं।

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

मान लीजिए कि आपके पास service.Execute(placeOrderOnHoldCommand) के लिए एक (एकीकरण) परीक्षण है, तो मुझे वास्तव में यह सुनिश्चित नहीं है कि यह जांच करने के लिए मूल्य जोड़ता है कि सेवा वास्तव में एक बार भंडार से ऑर्डर लोड करती है या नहीं। लेकिन यह हो सकता है!उदाहरण के लिए जब आपकी सेवा में पहले एक बुरा बग था जो एक आदेश के लिए दस बार भंडार को दबाएगा, जिससे प्रदर्शन के मुद्दे (बस इसे बनाते हैं)। उस स्थिति में, मैं परीक्षण को PlaceOrderOnHold_LoadsOrderFromRepositoryExactlyOnce() पर पुनर्नामित कर दूंगा।

तो प्रत्येक परीक्षण के लिए आपको अपने लिए निर्णय लेना होगा ... उम्मीद है कि मदद करता है।

नोट्स:

  1. परीक्षण आप पूरी तरह से वैध हो सकता है और अच्छी तरह से लिखा देख सकते हैं दिखा।

  2. आपकी टेस्ट अनुक्रम विधियां वर्तमान में Execute(...) विधि को लागू करने के तरीके से प्रेरित होती हैं। जब आप इस तरह अपना परीक्षण तैयार करते हैं, तो यह हो सकता है कि आप एक विशिष्ट कार्यान्वयन के लिए खुद को बांध रहे हों। इस तरह, परीक्षण वास्तव में इसे बदलने में कठिन बना सकते हैं - सुनिश्चित करें कि आप केवल अपनी कक्षा के महत्वपूर्ण बाहरी व्यवहार का परीक्षण कर रहे हैं।

+1

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

4

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

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

मैं एक लाइनर के साथ विधियों का परीक्षण करने के लिए परेशान नहीं हूं जब तक कि उस पंक्ति में कुछ बोसिन तर्क न हो।

अपडेट: बस इसे स्पष्ट करने के लिए, क्योंकि मैं परीक्षण संचालित विकास कर रहा हूं, मैं हमेशा यूनिट परीक्षण लिखता हूं और आम तौर पर अंत में एकीकरण परीक्षण करता हूं।

10

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

[Test] 
public void PlaceOrderOnHold_LoadsOrderFromRepository() 
{ 
    const int orderId = 1; 
    var repository = new MyMockRepository(); 
    repository.save(new MyMockOrder(orderId));  
    var command = new PlaceOrderOnHoldCommand(orderId); 
    var service = new OrderService(repository); 
    service.Execute(command); 
    Assert.IsTrue(repository.getOrder(orderId).isOnHold()); 
} 

यह सुनिश्चित करने के लिए वास्तव में कोई आवश्यकता नहीं है कि लोड और/या सहेजें कहा जाता है। इसके बजाए मैं केवल यह सुनिश्चित कर दूंगा कि MyMockRepository अद्यतन आदेश लौटाए जाने का एकमात्र तरीका यह है कि लोड और सेव कॉल कहा जाता है।

इस प्रकार का सरलीकरण उन कारणों में से एक है जिनसे मैं आमतौर पर नकली ढांचे का उपयोग नहीं करता हूं। ऐसा लगता है कि आपके परीक्षणों पर आपके पास बहुत बेहतर नियंत्रण है, और यदि आप अपना खुद का झटका लिखते हैं, तो उन्हें लिखने में एक आसान समय है।

+1

दिलचस्प चाचा बॉब लें। माना जाता है कि यह अचानक अचानक समाप्त हुआ :) –

+0

लेकिन शायद 'ऑर्डर। प्लेसऑनहोल्ड() 'के लिए भी परीक्षण किया गया है। तो अगर अब आप तय करते हैं कि आईडी 1 के साथ ऑर्डर को नहीं रखा जा सकता है, तो आपके पास – driushkin

+0

@unclebob को ठीक करने के लिए 2 परीक्षण हैं! मैं इसे ध्यान में रखना चाहता हूं। @driushkin निश्चित रूप से 'Order.PlaceOnHold()' के लिए एक परीक्षण है। हालांकि, क्या होल्ड पर ऑर्डर दिया जा सकता है, पूरी तरह से असली ऑर्डर क्लास को कार्यान्वित करने की चिंता है - नकली का कोई तरीका नहीं होगा कि सेवा विधि में क्या होना चाहिए। –

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