2009-04-07 4 views
7

मैं यूनिट का उपयोग करके कुछ कोड परीक्षण करने का प्रयास कर रहा हूं।एएसपी.नेट एमवीसी - सिस्टम.Web.Compilation.CompilationLock

public static string RenderRoute(HttpContextBase context, RouteValueDictionary values) 
    { 
     var routeData = new RouteData(); 
     foreach (var kvp in values) 
     { 
      routeData.Values.Add(kvp.Key, kvp.Value); 
     } 

     string controllerName = routeData.GetRequiredString("controller"); 
     var requestContext = new RequestContext(context, routeData); 
     IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory(); 
     IController controller = factory.CreateController(requestContext, controllerName); 

     var ActionInvoker = new ControllerActionInvoker(); 
     var controllerContext = new ControllerContext(requestContext, (ControllerBase)controller); 
     ((ControllerBase)controller).ControllerContext = controllerContext; 

     string actionName = routeData.GetRequiredString("action"); 

     Action action = delegate { ActionInvoker.InvokeAction(controllerContext, actionName); }; 

     return new BlockRenderer(context).Capture(action); 
    } 

मेरे डिफ़ॉल्ट controllerfactory MvcContrib से एक StructureMap नियंत्रक कारखाना है: मैं एक विधि है। मैं MvcContrib से MvcMockHelpers का भी उपयोग कर रहा हूं ताकि मुझे HttpContextBase का मज़ाक उड़ा सकें।

नियंत्रक मैं परीक्षण करने के लिए प्रयास कर रहा हूँ ऊपर RenderRoute प्रणाली को बुलाती है और पर चल रही है:

Controllers.WidgetControllerTests.CanCreateWidgetOnPage: System.Web.HttpException: त्रुटि के साथ

IController controller = factory.CreateController(requestContext, controllerName); 

'System.Web.Compilation.CompilationLock' के लिए प्रारंभकर्ता टाइप करें अपवाद फेंक दिया। ----> System.TypeInitializationException: 'System.Web.Compilation.CompilationLock' के लिए प्रकार प्रारंभकर्ता एक अपवाद फेंक दिया। ----> System.NullReferenceException: ऑब्जेक्ट संदर्भ किसी ऑब्जेक्ट के उदाहरण पर सेट नहीं है।

मैं यूनिट परीक्षण/मॉकिंग के लिए बिल्कुल नया हूं और यह संभावना है कि मैं कुछ सरल नहीं देख रहा हूं।

[Test] 
    public void Test() 
    { 
     HttpContextBase context = MvcMockHelpers.DynamicHttpContextBase(); 
     string s = RenderExtensions.RenderAction<HomeController>(context, a => a.About()); 

     Console.WriteLine(s); 
     Assert.IsNotNullOrEmpty(s); 
    } 

किसी भी मदद की सराहना की जाएगी:

यहाँ परीक्षण मैं वर्तमान में चल रहा हूँ है।

मैं इस सरल इकाई परीक्षण करने के लिए नीचे समस्या को सरल बनाया गया है:

[Test] 
    public void Test2() 
    { 
     HttpContextBase context = MvcMockHelpers.DynamicHttpContextBase(); 
     var routeData = new RouteData(); 
     routeData.Values.Add("Controller", "Home"); 
     routeData.Values.Add("Action", "About"); 


     string controllerName = routeData.GetRequiredString("controller"); 
     var requestContext = new RequestContext(context, routeData); 
     IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory(); 
     IController controller = factory.CreateController(requestContext, controllerName); 

     Assert.IsNotNull(controller); 
    } 

उत्तर

3

मैं जब इकाई परीक्षण करने के लिए एक नियंत्रक कारखाने मैंने लिखा प्रयास कर यह एक ही मुद्दे में भाग गया।

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

एमवीसीसीओन्ट्रिब यूनिट ने अपने नियंत्रक कारखानों का परीक्षण करने के तरीके को देखते हुए पाया कि वे एक विस्तार विधि सहायक का उपयोग कर रहे हैं जो एक निजी संपत्ति तक पहुंचने के लिए प्रतिबिंब का उपयोग कर नियंत्रक कैश को ओवरराइड करता है।

using System; 
using System.Linq; 
using System.Reflection; 
using System.Web.Mvc; 

public static class ControllerFactoryTestExtension 
{ 
    private static readonly PropertyInfo _typeCacheProperty; 
    private static readonly FieldInfo _cacheField; 

    static ControllerFactoryTestExtension() 
    { 
     _typeCacheProperty = typeof(DefaultControllerFactory).GetProperty("ControllerTypeCache", BindingFlags.Instance | BindingFlags.NonPublic); 
     _cacheField = _typeCacheProperty.PropertyType.GetField("_cache", BindingFlags.NonPublic | BindingFlags.Instance); 
    } 

    /// <summary> 
    /// Replaces the cache field of a the DefaultControllerFactory's ControllerTypeCache. 
    /// This ensures that only the specified controller types will be searched when instantiating a controller. 
    /// As the ControllerTypeCache is internal, this uses some reflection hackery. 
    /// </summary> 
    public static void InitializeWithControllerTypes(this IControllerFactory factory, params Type[] controllerTypes) 
    { 
     var cache = controllerTypes 
      .GroupBy(t => t.Name.Substring(0, t.Name.Length - "Controller".Length), StringComparer.OrdinalIgnoreCase) 
      .ToDictionary(g => g.Key, g => g.ToLookup(t => t.Namespace ?? string.Empty, StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase); 

     var buildManager = _typeCacheProperty.GetValue(factory, null); 
     _cacheField.SetValue(buildManager, cache); 
    } 
} 

कहा कि मेरी इकाई परीक्षण परियोजना के लिए मैं controllerFactory.InitializeWithControllerTypes(new[] {typeof(MockController)});

का उपयोग कर नियंत्रक प्रकार कैश करने के लिए अपने खुद के MockController प्रकार जोड़ने के लिए सक्षम था के बाद
संबंधित मुद्दे