2010-03-13 16 views
20

मैं एक नियंत्रक कि एक इकाई पर एक साधारण संचालन जोड़ें लागू करता है और विवरण पृष्ठ पर रीडायरेक्ट है: (से RedirectToAction का उपयोग करयूनिट ASP.NET में एक नियंत्रक परीक्षण MVC 2 RedirectToAction साथ

[HttpPost] 
public ActionResult Add(Thing thing) 
{ 
    // ... do validation, db stuff ... 
    return this.RedirectToAction<c => c.Details(thing.Id)); 
} 

यह अच्छा काम करता है एमवीसी कॉन्ट्रिब असेंबली)।

जब मैं इस विधि का परीक्षण कर रहा हूं, तो मैं विवरण कार्रवाई से वापस लौटाए गए व्यूडेटा तक पहुंचना चाहता हूं (इसलिए मैं नई डाली गई चीज़ की प्राथमिक कुंजी प्राप्त कर सकता हूं और साबित करता हूं कि यह अब डेटाबेस में है)।

परीक्षण है:

var result = controller.Add(thing); 

लेकिन परिणाम यहाँ प्रकार का है: System.Web.Mvc.RedirectToRouteResult (जो एक System.Web.Mvc.ActionResult है)। यह अभी तक विवरण विधि निष्पादित नहीं किया है।

मैंने ExecuteResult को मॉक किए गए ऑब्जेक्ट पर ControllerContext में गुजरने वाली लौटाई गई वस्तु पर कॉल करने का प्रयास किया है लेकिन मॉक ऑब्जेक्ट में विस्तार की कमी से ढांचा खुश नहीं था।

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

क्या मुझे परीक्षण दर्शन में कुछ याद आ रही है? जब मैं अपने लौटे राज्य में नहीं मिल पाता हूं तो मैं इस कार्रवाई का परीक्षण कैसे करूं?

उत्तर

7

आप एक यूनिट परीक्षण के लिए बहुत अधिक रास्ता कर रहे हैं। सत्यापन और डेटा एक्सेस आमतौर पर उन सेवाओं द्वारा की जाती है जिन्हें आप नियंत्रक कार्रवाई से कॉल करते हैं। आप उन सेवाओं का मज़ाक उड़ाते हैं और केवल परीक्षण करते हैं कि उन्हें ठीक से बुलाया गया था।

कुछ इस तरह (Rhino.Mocks & NUnit के लिए अनुमानित सिंटैक्स का उपयोग):

[Test] 
public void Add_SavesThingToDB() 
{ 
    var dbMock = MockRepository.GenerateMock<DBService>(); 
    dbMock.Expect(x => x.Save(thing)).Repeat.Once(); 

    var controller = new MyController(dbMock); 
    controller.Add(new Thing()); 

    dbMock.VerifyAllExpectations(); 
} 

[Test] 
public void Add_RedirectsAfterSave() 
{ 
    var dbMock = MockRepository.GenerateMock<DBService>(); 

    var controller = new MyController(dbMock); 
    var result = (RedirectToRouteResult)controller.Add(new Thing()); 

    Assert.That(result.Url, Is.EqualTo("/mynew/url")); 
} 
+0

धन्यवाद - यह निश्चित रूप से परीक्षण के दौरान ढांचे के साथ कठिनाइयों से बचने में मदद करता है। इसलिए, इस मुहावरे के बाद मेरे पास डीबीएस सेवा के लिए यूनिट परीक्षण होंगे जो साबित करता है कि मैं चीजों को जोड़ सकता हूं, और नियंत्रक के लिए एक इकाई परीक्षण साबित कर रहा हूं कि इसकी कॉल सेवा पर सहेजें। लेकिन मैंने वास्तव में साबित नहीं किया है कि नियंत्रक में पास की गई चीज़ डेटाबेस में समाप्त होती है। हो सकता है कि मैं इसे पूरे समूह के साथ अधिक जटिल मॉकिंग नियमों के साथ कर सकता हूं ... लेकिन यह सही नहीं लगता है, यह एक सरल ऑपरेशन के लिए बहुत सारे टेस्ट बॉयलर प्लेट है। –

+0

ठीक है, परीक्षणों और परीक्षणों के परीक्षण के लिए दायरे और प्रयास का निर्धारण करना, कुछ ऐसा है जो मैं भी संघर्ष करता हूं। मुझे लगता है कि आपको अपने परीक्षणों को दो श्रेणियों में अलग करने की कोशिश करनी चाहिए: यूनिट परीक्षण और एकीकरण परीक्षण। यूनिट परीक्षणों को कार्यक्षमता की केवल बहुत छोटी इकाइयों का परीक्षण करना चाहिए, जैसे उपर्युक्त परीक्षण। एकीकरण परीक्षणों को देखना चाहिए कि सबकुछ कैसे एकीकृत होता है, हो सकता है कि आपके पास एक छोटी उपयोगकर्ता कहानी हो। मैं एकीकरण परीक्षण को यथासंभव करीब "असली" उपयोग करना पसंद करूंगा, उदाहरण के लिए WatiN चला रहा हूं और वास्तव में कुछ लिंक पर क्लिक कर रहा हूं। वहां पर नकली करने की कोई ज़रूरत नहीं है। – rmac

+0

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

12

MVC योगदान TestHelper कि ActionResult

के सबसे परीक्षण आप इसे यहाँ प्राप्त कर सकते हैं के लिए शानदार रहे हैं नहीं है:

: http://mvccontrib.codeplex.com/wikipage?title=TestHelper

यहाँ वाक्य रचना का एक उदाहरण है

यह जांचने के लिए कि क्या डेटा सफलतापूर्वक जारी रखा गया है, आपको शायद अपने डेटाबेस से सीधे पूछना चाहिए, मुझे नहीं पता कि आप ओआरएम या कुछ का उपयोग कर रहे हैं, लेकिन आपको अपने आखिरी इंस्टेंट आइटम को प्राप्त करने के लिए कुछ करना चाहिए डेटाबेस, फिर अपने ऐड एक्शन रिसेट में दिए गए मान से तुलना करें और देखें कि यह ठीक है या नहीं।

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

लेकिन आपको यह सुनिश्चित करने के लिए इकाई को अपनी विवरण विधि का परीक्षण करना चाहिए कि आपकी व्यूडेटा ऑब्जेक्ट आपके डेटाबेस से आने वाले सही डेटा से भरा हुआ है।

31

मैं इस समय एमवीसी 2 आरसी 2 का उपयोग कर रहा हूं और आरएमएसीएफई का जवाब मेरे लिए काफी काम नहीं करता था लेकिन मुझे सही रास्ते पर ले गया।

सही हो या गलत मैं बजाय अपने परीक्षण में ऐसा करने में कामयाब रहे:

var actionResult = (RedirectToRouteResult)logonController.ForgotUsername(model); 

actionResult.RouteValues["action"].should_be_equal_to("Index"); 
actionResult.RouteValues["controller"].should_be_equal_to("Logon"); 

सुनिश्चित नहीं हैं कि अगर यह किसी को मदद मिलेगी, लेकिन आप 10 मिनट बचाने के लिए हो सकता है।

+2

बहुत बढ़िया! आप इसी तरह से अतिरिक्त मार्ग मूल्यों की जांच कर सकते हैं। 'रीडायरेक्ट टॉक्शन (" विवरण "," व्यक्ति ", {personId = 123}) के लिए 'आप' व्यक्ति आईडी 'की जांच कर सकते हैं:' Assert.AreEqual (123, actionResult.RouteValues ​​[" personId "]) ' – Kirill

6

मेरे पास एक स्थिर सहायक विधि है जो पुनर्निर्देशन का परीक्षण करती है।

public static class UnitTestHelpers 
{ 
    public static void ShouldEqual<T>(this T actualValue, T expectedValue) 
    { 
     Assert.AreEqual(expectedValue, actualValue); 
    } 

    public static void ShouldBeRedirectionTo(this ActionResult actionResult, object expectedRouteValues) 
    { 
     RouteValueDictionary actualValues = ((RedirectToRouteResult)actionResult).RouteValues; 
     var expectedValues = new RouteValueDictionary(expectedRouteValues); 

     foreach (string key in expectedValues.Keys) 
     { 
      Assert.AreEqual(expectedValues[key], actualValues[key]); 
     } 
    } 
} 

फिर एक पुनर्निर्देशन परीक्षण बनाना बहुत आसान है।

[Test] 
public void ResirectionTest() 
{ 
    var result = controller.Action(); 

    result.ShouldBeRedirectionTo(
     new 
     { 
      controller = "ControllerName", 
      action = "Index" 
     } 
    ); 
} 
+3

+1 एक्सटेंशन विधि के लिए +1 लेकिन किसी कारण से एमवीसी 3 नियंत्रक का नाम शून्य है –

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