2012-03-22 15 views
11

पर MVCContrib का उपयोग करते समय रूटडेटा को कुंजी और मान जोड़ें, ठीक है, इसलिए मैं अपने नियंत्रकों की इकाई परीक्षण करने के लिए एमवीसीसींट्रिब टेस्टहेल्पर का उपयोग कर रहा हूं, जो बहुत अच्छा काम करता है।यूनिट परीक्षण एमवीसी 3 नियंत्रकों और दृश्य

हालांकि कई लोगों की तरह, यूनिट परीक्षण द्वारा मैं वास्तव में यहां एकीकरण परीक्षण का मतलब रखता हूं और मैं कम से कम यह सुनिश्चित करना चाहता हूं कि मेरे विचार मॉडल के बिना त्रुटि के बिना प्रस्तुत किए जाएं ... अन्यथा मैं मूल रूप से संबंधित बग की पूरी कक्षा को याद कर सकता हूं मॉडल के लिए भले ही मैं नियंत्रक का परीक्षण कर रहा हूं (जैसे कि मॉडल प्रॉपर्टी शून्य है तो दृश्य प्रस्तुत नहीं कर रहा है)।

वैसे भी मैंने यह पता लगाने की कोशिश की कि यह कैसे करना है (उर्फ गुगलिंग यह कैसे करें)। ऐसा लगता है कि एक HTMLHelper बनाने का सबसे आसान तरीका था और इसे केवल विचार प्रस्तुत करना (इस मामले में आंशिक)।

दुर्भाग्यवश जब मैं अपने मॉक किए गए HTMLHelper का उपयोग करने का प्रयास करता हूं तो यह शिकायत करता है कि रूट डेटा में नियंत्रक का नाम उपलब्ध नहीं है।

निश्चित रूप से, मैं देखता हूं और नियंत्रक रूटडेटा पॉप्युलेट नहीं होता है। दुर्भाग्यवश RouteData.Values ​​RouteValueDictionary केवल पढ़ा जाता है, इसलिए मैं केवल आवश्यक मानों की आपूर्ति नहीं कर सकता।

मैं परीक्षण के हिस्से के रूप में वास्तव में दृश्य प्रस्तुत करने की समस्या को हल करने के लिए HTMLHelper विचार से विवाहित नहीं हूं, इसलिए वहां विकल्पों का सुझाव देने में संकोच न करें, लेकिन कृपया चिंता न करें कि मैं सेलेनियम का उपयोग करके अपने विचारों का परीक्षण करता हूं, वाटिन या अन्य यूआई परीक्षण उपकरण ... मैं चाहता हूं कि नियंत्रण कुछ चीजों के लिए राज्य और डेटा जानकारी को मैनिपुलेट और पुनर्स्थापित करने में सक्षम हो, जो मैं यूआई आधारित परीक्षण के साथ नहीं कर सकता। यहाँ

public class FakeView : IView 
{ 
    #region IView Members 
    public void Render(ViewContext viewContext, System.IO.TextWriter writer) 
    { 
     throw new NotImplementedException(); 
    } 
    #endregion 
} 

public class WebTestUtilities 
{ 
    public static void prepareCache() 
    { 
     SeedDataManager seed = new SeedDataManager(); 
     seed.CheckSeedDataStatus(); 
    } 

    public static string RenderRazorViewToString(string viewName, object model, Controller controller) 
    { 
     var sb = new StringBuilder(); 
     var memWriter = new StringWriter(sb); 
     var html = new HtmlHelper(new ViewContext(controller.ControllerContext, 
      new FakeView(), new ViewDataDictionary(), new TempDataDictionary(), memWriter), 
      new ViewPage()); 
     //This fails because it can't extract route information like the controller name) 
     html.RenderPartial(viewName, model); 
     return sb.ToString(); 
    } 


    public void setupTestEnvironment(Controller controller) 
    { 
     RouteTable.Routes.Clear(); 
     RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

     RouteTable.Routes.MapRoute(
      "Default", 
      "{controller}/{action}/{id}", 
      new { controller = "Main", action = "DefaultView", id = UrlParameter.Optional } 
     ); 




     ModelBinders.Binders[typeof(DateTime)] = new DateTimeModelBinder(); 
     ModelBinders.Binders[typeof(DateTime?)] = new DateTimeModelBinder(); 
     ModelMetadataProviders.Current = new DateTimeMetadataProvider(); 



    } 
} 

और मेरी परीक्षा पद्धति है::

यहाँ कोड मैं वर्तमान में आंशिक रेंडर करने के लिए प्रयास करने के लिए उपयोग कर रहा हूँ है

 [TestMethod] 
    public void GetUserTableView() 
    { 
     ViewResult result = controller.UserTable() as ViewResult; 

     //I can populate the route and handler on the controller... 
     RouteData routes = RouteTable.Routes.GetRouteData(controller.HttpContext); 
     controller.RouteData.Route = routes.Route; 
     controller.RouteData.RouteHandler = routes.RouteHandler; 
     RouteValueDictionary routeKeys = new RouteValueDictionary(); 
     routeKeys.Add("controller", "UserManagement"); 
     routeKeys.Add("action", "UserTable"); 
     //But the RouteData.Values collection is read only :(
     controller.RouteData = new RouteData(){Values = routeKeys}; 
     string renderedView = WebTestUtilities.RenderRazorViewToString(result.ViewName, result.Model, controller); 
    } 

Btw, विशिष्ट त्रुटि मैं मिलता है: रूटडेटा में एक गैर-खाली स्ट्रिंग मान वाले 'नियंत्रक' नामक एक आइटम होना चाहिए।

उत्तर

26

आप पहले से ही हो सकता है इस पर काम किया है, लेकिन मैं सिर्फ एक समान समस्या थी और नियंत्रक पर ControllerContext रीसेट करके RouteData की स्थापना हल इसलिए जैसे:

RouteData routeData = new RouteData(); 
routeData.Values.Add("someRouteDataProperty", "someValue"); 
ControllerContext controllerContext = new ControllerContext { RouteData = routeData }; 
controller.ControllerContext = controllerContext; 

और फिर नियंत्रक RouteData.Values.ContainsKey ("someRouteDataProperty") में के रूप में आप परीक्षण में सेट किए गए काम करता है।

यह काम करता है मजाक आदि

+0

बहुत अच्छा काम करता है, धन्यवाद। बेशक अब मुझे यह समझना होगा कि विचारों के पथ को कैसे हल किया जाए क्योंकि मुझे "एप्लिकेशन रिश्तेदार आभासी पथ पूर्ण नहीं किया जा सकता" त्रुटियां, लेकिन इस भाग ने कम से कम काम किया। – Amasuriel

2

आप नियंत्रक ControllerContext.RouteData ओवरराइड कर सकते हैं - इसकी आभासी और रूटडेटा संपत्ति बस इसे पढ़ने के लिए उपयोग कर रही है।

asp.net MVC के RouteData संपत्ति का परिलक्षित कोड से:

public RouteData RouteData 
{ 
    get 
    { 
     return ControllerContext == null ? null : ControllerContext.RouteData; 
    } 
} 
+0

लेकिन तब मैं एक संशोधित नियंत्रक वर्ग जो मैं नहीं करना चाहता होगा उपयोग करने के लिए अनुमति देने के लिए जान-बूझकर यह है कि ControllerContext की एक parameterless निर्माता है क्योंकि। – Amasuriel

+0

नहीं, आपको इसकी आवश्यकता नहीं है – Sly

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