2013-06-18 10 views
6

Ho un metodo scritto che converte la vista MVC in stringa e il metodo di prova per verificare se restituisce una stringa.Metodo di test dell'unità che converte la vista MVC in stringa utilizzando il metodo view.render

Naturalmente funziona con Web ma quando eseguo test in NUnit genera una NullReferenceException in System.Web quando il metodo tenta di chiamare View.Render.

Ecco StackTrace:

w System.Web.VirtualPath.GetCacheKey() 
    w System.Web.Compilation.BuildManager.GetCacheKeyFromVirtualPath(VirtualPath virtualPath, Boolean& keyFromVPP) 
    w System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, Boolean ensureIsUpToDate) 
    w System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) 
    w System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) 
    w System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound) 
    w System.Web.Compilation.BuildManager.GetObjectFactory(String virtualPath, Boolean throwIfNotFound) 
    w System.Web.Mvc.BuildManagerWrapper.System.Web.Mvc.IBuildManager.FileExists(String virtualPath) 
    w System.Web.Mvc.BuildManagerViewEngine.FileExists(ControllerContext controllerContext, String virtualPath) 
    w System.Web.Mvc.VirtualPathProviderViewEngine.GetPathFromSpecificName(ControllerContext controllerContext, String name, String cacheKey, String[]& searchedLocations) 
    w System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext, String[] locations, String[] areaLocations, String locationsPropertyName, String name, String controllerName, String cacheKeyPrefix, Boolean useCache, String[]& searchedLocations) 
    w System.Web.Mvc.VirtualPathProviderViewEngine.FindView(ControllerContext controllerContext, String viewName, String masterName, Boolean useCache) 
    w System.Web.Mvc.ViewEngineCollection.<>c__DisplayClassc.<FindView>b__b(IViewEngine e) 
    w System.Web.Mvc.ViewEngineCollection.Find(Func`2 lookup, Boolean trackSearchedPaths) 
    w System.Web.Mvc.ViewEngineCollection.Find(Func`2 cacheLocator, Func`2 locator) 
    w System.Web.Mvc.ViewEngineCollection.FindView(ControllerContext controllerContext, String viewName, String masterName) 
    w MvcApplication.Infrastructure.Services.MailingService.RenderEmailBody[T](String viewPath, T model, ControllerContext controllerContext, Boolean isParialView) w d:\MyProjects\CertyfikatyNoble\branches\Certyfikaty3\MvcApplication\Infrastructure\Services\MailingService.cs:wiersz 175 
    w MvcApplication.Tests.MailingServiceTests.ViewToStrngTest() w d:\MyProjects\CertyfikatyNoble\branches\Certyfikaty3\MvcApplication.Tests\MailingServiceTests.cs:wiersz 144 

Rendering codice di metodo: il metodo

public string RenderEmailBody<T>(string viewPath, T model, ControllerContext controllerContext, bool isParialView) 
{ 
    ViewEngineResult viewEngineResult = null; 
    if (isParialView == true) 
    { 
     viewEngineResult = ViewEngines.Engines.FindPartialView(controllerContext, viewPath); 
    } 
    else 
    { 
     viewEngineResult = ViewEngines.Engines.FindView(controllerContext, viewPath, null); 
    } 

    if (viewEngineResult == null) 
    { 
     throw new FileNotFoundException("Coukld not find view."); 
    } 

    var view = viewEngineResult.View; 
    controllerContext.Controller.ViewData.Model = model; 

    string result = null; 

    using (var sw = new StringWriter()) 
    { 
     var ctx = new ViewContext(controllerContext, view, 
            controllerContext.Controller.ViewData, 
            controllerContext.Controller.TempData, 
            sw); 
     view.Render(ctx, sw); 
     result = sw.ToString(); 
    } 

    return result; 
} 

e il test con il contesto regolatore finto:

 Mock<HttpBrowserCapabilitiesBase> browserMock = new Mock<HttpBrowserCapabilitiesBase>(); 
     browserMock.Setup(m => m.IsMobileDevice).Returns(false); 

     Mock<HttpServerUtilityBase> httpServerUtilityBaseMock = new Mock<HttpServerUtilityBase>(MockBehavior.Strict); 

     Mock<HttpResponseBase> httpResponseMock = new Mock<HttpResponseBase>(MockBehavior.Strict); 
     httpResponseMock.Setup(m => m.Cookies).Returns(new HttpCookieCollection() { new HttpCookie("ResponseCookieTest") }); 

     Mock<HttpRequestBase> httpRequestMock = new Mock<HttpRequestBase>(MockBehavior.Strict); 
     httpRequestMock.Setup(m => m.UserHostAddress).Returns("127.0.0.1"); 
     httpRequestMock.Setup(m => m.Cookies).Returns(new HttpCookieCollection() { new HttpCookie("RequestCookieTest") }); 
     httpRequestMock.Setup(m => m.UserAgent).Returns("None"); 
     httpRequestMock.Setup(m => m.Browser).Returns(browserMock.Object); 
     httpRequestMock.Setup(m => m.ApplicationPath).Returns("/"); 
     httpRequestMock.Setup(m => m.AppRelativeCurrentExecutionFilePath).Returns("/"); 
     httpRequestMock.Setup(m => m.PathInfo).Returns(string.Empty); 
     httpRequestMock.Setup(m => m.Form).Returns(new NameValueCollection()); 
     httpRequestMock.Setup(m => m.QueryString).Returns(new NameValueCollection()); 

     Mock<HttpSessionStateBase> httpSessionStateMock = new Mock<HttpSessionStateBase>(MockBehavior.Strict); 
     httpSessionStateMock.Setup(m => m.SessionID).Returns(Guid.NewGuid().ToString()); 


     Mock<HttpContextBase> HttpContextMock = new Mock<HttpContextBase>(MockBehavior.Strict); 
     HttpContextMock.Setup(m => m.Request).Returns(httpRequestMock.Object); 
     HttpContextMock.Setup(m => m.Response).Returns(httpResponseMock.Object); 
     HttpContextMock.Setup(m => m.Server).Returns(httpServerUtilityBaseMock.Object); 
     HttpContextMock.Setup(m => m.Session).Returns(httpSessionStateMock.Object); 

     HttpContextMock.Setup(m => m.Items).Returns(new ListDictionary()); 

     RouteData routeData = new RouteData(); 
     routeData.Values.Add("controller", "someController"); 
     routeData.Values.Add("action", "index"); 

     Mock<ControllerContext> controllerContextMock = new Mock<ControllerContext>(MockBehavior.Strict); 
     controllerContextMock.Setup(m => m.HttpContext).Returns(HttpContextMock.Object); 
     controllerContextMock.Setup(m => m.RouteData).Returns(routeData); 
     controllerContextMock.Setup(m => m.Controller).Returns(new AccountController()); 

     SiteConfigurationService siteConfigurationService = SiteConfigurationService.Instance(); 
     siteConfigurationService.LoadConfig<SiteConfigurations>(this._siteConfigurationsRepository.GetDefaultConfig()); 

     MailingService service = new MailingService(controllerContextMock.Object, siteConfigurationService); 

     string result = service.RenderEmailBody<object>("/ViewToRenderToString.cshtml", new object(), controllerContextMock.Object, false); 

ho letto HERE che la causa è che _virtualPath e HttpRuntime.AppDomainAppVirtualPathString int System.Web.VirtualP athString sono NULL.

Quindi è possibile impostarli per il test dell'unità?

Grazie in anticipo,

+0

L'ho esaminato abbastanza ampiamente in un'occasione precedente ed è difficile. Quello che potresti fare invece è renderizzare il tuo corpo e-mail come al solito e leggerlo usando un WebRequest o altro. Quindi esegui un test di integrazione nel caso in cui desideri vedere come esegue il rendering. – JuhaKangas

+0

cose che ho fatto quando stavo cercando di realizzare questo senza ricorrere a una richiesta web: accendere consentire .net framework stepping e/o scaricare il codice sorgente di mvc, decompilare l'assembly che presenta errori direttamente. Non penso di averlo realizzato, ma sono MOLTO interessato a una risposta – Maslow

risposta

0

Hai provato implementare il proprio VirtualPathProvider?

Qualcosa di simile a questo:

public class CustomVirtualPathProvider : VirtualPathProvider 
    { 
     internal class CustomVirtualFile : ViewVirtualFile 
     { 
      public override bool IsDirectory 
      { 
       get 
       { 
        return base.IsDirectory; 
       } 
      } 
      public override string Name 
      { 
       get 
       { 
        return base.Name; 
       } 
      } 
      public override string ResourceKey 
      { 
       get 
       { 
        return base.ResourceKey; 
       } 
      } 
      public override System.IO.Stream Open() 
      { 
       return base.Open(); 
      } 
      public CustomVirtualFile(string path) 
       : base(path) 
      { 

      } 

     } 
     public override bool FileExists(string virtualPath) 
     { 
      return base.FileExists(virtualPath); 
     } 
     public override VirtualFile GetFile(string virtualPath) 
     { 
      return base.GetFile(virtualPath); 
     } 
     public override VirtualDirectory GetDirectory(string virtualDir) 
     { 
      return base.GetDirectory(virtualDir); 
     } 
     public override bool DirectoryExists(string virtualDir) 
     { 
      return base.DirectoryExists(virtualDir); 
     } 


    } 

Poi nel Global.asax

///register our custom virtual path provider factory. 
      HostingEnvironment.RegisterVirtualPathProvider(new CustomVirtualPathProvider()); 

Con questo approccio, si può rendere una vista da qualsiasi luogo.