2015-01-22 20 views
7

Geniş ve karmaşık raporlar üreten bir ASP.NET MVC 4 web uygulaması üzerinde çalışıyorum. Eminim Görünüm Modeli bağlı patlatmasa kılmak için Görünüm hale Birimi Testleri yazmak istiyorum:Bir Birim Testi sırasında Görünüm Oluşturma - ControllerContext.DisplayMode

[Test] 
public void ExampleTest(){     
    var reportModel = new ReportModel(); 

    var reportHtml = RenderRazorView(
      @"..\..\Report.Mvc\Views\Report\Index.cshtml", 
      reportModel); 

    Assert.IsFalse(
     string.IsNullOrEmpty(reportHtml), 
     "View Failed to Render!");   
} 

public string RenderRazorView(string viewPath, object model){ 
    //WHAT GOES HERE? 
} 

Ben web etrafında bu konuda birçok bilgi gördük, ama ya var test vies aleyhine tartışmak, ya da sadece bir web isteği bağlamında kullanılabilir. Unit Testing the Views? - - Karşı savunan

  • Bu, yalnızca derleme test etmek gerekir bu yüzden görünümünde hiçbir mantığı olmamalıdır varır. Ben, doğru kesitler, gösterilen değeri değil null başvuru İstisnalar vardır emin olmak için Görüntüle test olduğunu düşünüyorum vb bir Web Talep
  • Bağlam
  • - Render a view as a string - Bu Bir Görünümü işlemek için bir de gönderilecek e-posta. Ancak bu yaklaşım bir web isteği ile çağrılmayı gerektirir (yani geçerli bir HttpContextBase).

Ben HttpContextBase alay ile çalışmak Render a view as a string uyarlamak için çalışıyoruz, ama bir ControllerContext alay kullanırken sorunlarla çalışan edilmiştir: bir nesnenin örneğine ayarlanmadı

nesne başvurusu. System.Web.Mvc.VirtualPathProviderViewEngine.GetPath de System.Web.Mvc.ControllerContext.get_DisplayMode() de System.Web.WebPages.DisplayModeProvider.GetDisplayMode (HttpContextBase bağlamı) (ControllerContext controllerContext, String [] yerle dize [az

public string RenderRazorView(string viewPath, object model) 
    { 
     var controller = GetMockedDummyController(); 

     //Exception here 
     var viewResult = 
      ViewEngines.Engines.FindView(controller.ControllerContext, "Index", ""); 

     using (var sw = new StringWriter()) 
     { 
      var viewContext = 
       new ViewContext(
        controller.ControllerContext, 
        viewResult.View, 
        new ViewDataDictionary(model), 
        new TempDataDictionary(), 
        sw); 

      viewResult.View.Render(viewContext, sw); 

      return sw.ToString(); 
     } 
    } 

inşa ediyorum:] areaLocations, dize locationsPropertyName, dize adı, dize controllerName, dize cacheKeyPrefix, Boole useCache, string [] & searchedLocations)

Bu kod var bugüne kadar olduğu kontrol eden, denetleyici:

private Controller GetMockedDummyController() 
    { 
     var HttpContextBaseMock = new Mock<HttpContextBase>(); 
     var HttpRequestMock = new Mock<HttpRequestBase>(); 
     var HttpResponseMock = new Mock<HttpResponseBase>(); 
     HttpContextBaseMock.SetupGet(x => x.Request).Returns(HttpRequestMock.Object); 
     HttpContextBaseMock.SetupGet(x => x.Response).Returns(HttpResponseMock.Object); 

     var controller = new DummyController(); 

     var routeData = new RouteData(); 
     routeData.Values.Add("controller", "Dummy"); 

     controller.ControllerContext = 
      new ControllerContext(
       HttpContextBaseMock.Object, 
       routeData, 
       controller); 

     controller.Url = 
      new UrlHelper(
       new RequestContext(
        HttpContextBaseMock.Object, 
        routeData), 
       new RouteCollection()); 

     return controller; 
    } 

DummyController sadece public class DummyController : Controller {}

Soru

nasıl bir test projesinden HTML işleyebilen bir Görünüm yolunu ver mı? Ya da daha spesifik olarak, ControllerContext.DisplayMode'u nasıl taklit edebilirim?

+0

Ben benzer bir sorun yaşıyorum gerekecektir. Sonunda bunun için herhangi bir çözüm buldunuz mu? Ayrıca ControllerContext.DisplayMode'u nasıl taklit edeceğimi merak ediyorum. – Shahin

+2

Maalesef, bunu yapmak için iyi bir çözüm bulamadım ve doğru bir şekilde hatırlarsam, Araştırma Başlığımda patladığım ve işe yarar bir şeyle geri dönmediğim için çabalarımı bırakmak zorunda kaldım. Test hikayesinin burada daha iyi olabileceğinden bazı yeni ASP.NET Core öğelerine göz atmak isteyebilirsiniz. Yaptıkları şeyin bir parçası olan AFAIK, buradaki temel problemlerden biri olan 'HttpContext''i izole etmektir. –

cevap

4

, sen endişeleri tamamen ayrılmasını var varsayarsak o hiç denetleyicisi örneğini gereklidir? Değilse, belki de görüşlerinizi test etmek için RazorEngine'u kullanabilirsiniz.

var contents = File.ReadAllText("pathToView"); 
var result = Razor.Parse(contents,model); 
// assert here 
+0

Hayır, Denetleyiciyi veya yöntemlerini çağırmam gerekmez. Zaten bir Modelim var ve bunu Görüntülemek için kullanmak istiyorum, bu yüzden bunu deneyeceğim! –

+0

"MVC" görünümlerini oluşturmak için bunu kullandınız mı? '@ Styles.Render()' gibi ifadeleri derleyemiyorum. Motor, onları eklemiş olmama rağmen eksik montajlardan şikayet ediyor. Derlenmiş çıktıya baktıktan sonra, ifadelerin web.config 'system.web \ pages \ namespaces' temel alınarak eklenmesi gibi görünüyor. Bunları eklemenin bir yolu var mı? –

+0

RazorEngine bağlantısında, montajların nasıl ele alınacağını ele alan belgeler bulunmaktadır. Evet, bunu görünümler ve dize şablonları için kullandım. Yine de iç içe geçmiş şablonları oluştururken kullanmadım. – B2K

0

Boş Controller sadece test için (ex TestController)

public class WebMvcHelpers 
{ 
    public static string GetViewPageHtml(object model, string viewName) 
    { 
     System.Web.Mvc.Controller controller = CreateController<TestController>(); 

     ViewEngineResult result = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName); 

     if (result.View == null) 
      throw new Exception(string.Format("View Page {0} was not found", viewName)); 

     controller.ViewData.Model = model; 
     StringBuilder sb = new StringBuilder(); 
     using (StringWriter sw = new StringWriter(sb)) 
     { 
      using (System.Web.UI.HtmlTextWriter output = new System.Web.UI.HtmlTextWriter(sw)) 
      { 
       ViewContext viewContext = new ViewContext(controller.ControllerContext, result.View, controller.ViewData, controller.TempData, output); 
       result.View.Render(viewContext, output); 
      } 
     } 

     return sb.ToString(); 
    } 

    /// <summary> 
    /// Creates an instance of an MVC controller from scratch 
    /// when no existing ControllerContext is present  
    /// </summary> 
    /// <typeparam name="T">Type of the controller to create</typeparam> 
    /// <returns></returns> 
    public static T CreateController<T>(RouteData routeData = null) 
       where T : System.Web.Mvc.Controller, new() 
    { 
     T controller = new T(); 

     // Create an MVC Controller Context 
     HttpContextBase wrapper = null; 
     if (HttpContext.Current != null) 
      wrapper = new HttpContextWrapper(System.Web.HttpContext.Current); 
     //else 
     // wrapper = CreateHttpContextBase(writer); 


     if (routeData == null) 
      routeData = new RouteData(); 

     if (!routeData.Values.ContainsKey("controller") && !routeData.Values.ContainsKey("Controller")) 
      routeData.Values.Add("controller", controller.GetType().Name 
                 .ToLower() 
                 .Replace("controller", "")); 

     controller.ControllerContext = new System.Web.Mvc.ControllerContext(wrapper, routeData, controller); 
     return controller; 
    } 
} 

public class TestController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(); 
    } 
} 
+0

Bu işe yaramaz. Hala HttpContext.Current' gerekiyor. "CreateHttpContextBase" yöntemi neden yorumlandı? Bunun için bir uygulaman var mı? –

+0

Hmm, hayır, bu yöntemin nereden geldiğini bilmiyorum. Ama [alay edebilir] (http://stackoverflow.com/questions/4379450/mock-httpcontext-current-in-test-init-method) 'HttpContext.Current' örneği – Catalin