2010-08-13 12 views
5

Próbuję nowego silnika widokowego Razor z podglądem 1 MVC i bardzo chciałbym napisać prosty test jednostkowy za pomocą NUnit/Moq. Nie widziałem żadnych przykładów tego, co faktycznie zostało zrobione - pomimo tego, że jest to jedna z rzeczy sprzedających się na maszynie Razor.Wskaźniki do napisania testu jednostkowego dla potrzebnego widoku Razor

Tak więc, jeśli posiadam kontroler, który używa obiektu DBConext (najpierw kod CTP EF4), a widok renderuje listę rozwijaną na podstawie listy elementów dostarczonych w modelu załadowanym w akcji wywołanej na kontrolerze , Chciałbym móc przetestować, czy element zawiera w nim elementy.

Oto mój Kontroler:

public class WeatherReportController : Controller, IWeatherReportController 
{ 
    private IWeatherDb _weatherDb; 

    public WeatherReportController() 
    { 
     this._weatherDb = new WeatherDb(); 
    } 

    public ActionResult Index() 
    { 
     WeatherReportIndexModel model = new WeatherReportIndexModel 
     { 
      Report = new WeatherReport { 
       Username = this.HttpContext.User.Identity.Name, 
       WeatherType = new WeatherType() 
      }, 
      WeatherTypeList = _weatherDb.GetAllWeatherTypes() 
     }; 
     return View(model); 
    } 

} 

Oto moja Model:

public class WeatherReportIndexModel 
{ 
    private IList<WeatherType> _weatherTypeList = new List<WeatherType>(); 
    public IList<WeatherType> WeatherTypeList { 
     get 
     { 
      return _weatherTypeList; 
     } 
     set 
     { 
      _weatherTypeList = value; 
     } 
    } 

    [DisplayName("Type of Weather")] 
    public IList<SelectListItem> WeatherTypeSelectItemList 
    { 
     get 
     { 
      int id = this.Report.WeatherType == null ? 0 : this.Report.WeatherType.WeatherTypeId; 
      List<SelectListItem> selectListItems = this.WeatherTypeList.Select(weatherType => new SelectListItem 
                        { 
                         Value = weatherType.WeatherTypeId.ToString(), 
                         Text = weatherType.Name, 
                         Selected = weatherType.WeatherTypeId == id 
                        }).ToList(); 
      selectListItems.Insert(0, new SelectListItem { Selected = (this.Report.WeatherType == null), Text = "Select Type of Weather", Value = "0" }); 
      return selectListItems; 
     } 
    } 

    public WeatherReport Report { get; set; } 
} 

I tu jest moim zdaniem:

@inherits System.Web.Mvc.WebViewPage<Web.UI.Models.WeatherReportIndexModel> 

@{ 
    View.Title = "Index"; 
    LayoutPage = "~/Views/Shared/_Layout.cshtml"; 
} 

<h2>Index</h2> 


@using (Html.BeginForm()) { 
    <div> 
     <fieldset> 
      <legend>New Weather Report</legend> 
      <div class="editor-label"> 
       @Html.LabelFor(m => m.Report.WeatherType.WeatherTypeId) 
       @Html.DropDownListFor(m => m.Report.WeatherType.WeatherTypeId, Model.WeatherTypeSelectItemList) 
    <input type="submit" value="Log On" /> 
      </div> 
    </fieldset> 
</div> 
} 

Kod testu mam tak daleko jest w następujący sposób:

[TestFixture] 
public class WeatherReportViewTests 
{ 
    [Test] 
    public void Can_render_weather_report_index_view_correctly() 
    { 

     var mockControllerContext = new Mock<ControllerContext>(); 
     var mockSession = new Mock<HttpSessionStateBase>(); 

     mockControllerContext.Setup(p => p.HttpContext.Request.HttpMethod).Returns("POST"); 
     mockControllerContext.Setup(p => p.HttpContext.Request.UserHostAddress).Returns("1.1.1.1"); 
     mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object); 
     mockControllerContext.Setup(p => p.HttpContext.Request.LogonUserIdentity).Returns(WindowsIdentity.GetCurrent()); 

     var routeData = new RouteData(); 
     routeData.Values.Add("controller", "WeatherReport"); 
     routeData.Values.Add("action", "Index"); 

     var viewEngine = new CshtmlViewEngine(); 
     var view = viewEngine.FindView(mockControllerContext.Object, "Index", "_Layout", false); 
     var viewReponse = view.ToString(); 

     Assert.That(viewReponse, Contains.Substring("Sunny Intervals")); 
    } 
} 

Po uruchomieniu testu otrzymuję wyjątek NullReferenceException.

Wszelkie pomysły/wskazówki itp. Byłyby mile widziane. Naprawdę chciałbym, żeby to działało, więc będę mógł tworzyć TDD na temat moich poglądów w przyszłości.

Z góry dziękuję!

+0

Niestety - po prostu zrobić aktualizacji do mojego kodu testowego - nadal zarysowania głowę choć :( – dextermixwith

+0

odrobinie szczęścia jeszcze I ty znalazł sposób, aby to funkcjonalne proszę podzielić go ... thx –

Odpowiedz

2

Sugerowałbym całkowite unikanie klasy CshtmlViewEngine i samodzielne uruchamianie silnika Razor. Napisałem post na blogu o kompilowaniu widoków Razor poza ASPX tutaj: http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of-aspnet.html

W podglądzie 1 MVC3 silnik Razor jest osadzony w System.Web.Mvc i jest publiczny (IIRC), więc powinieneś być w stanie znaleźć wszystkie klasy, do których odwołuje się ten post/sample w System.Web.Mvc.dll.

Po skompilowaniu strony, wystarczy załadować wygenerowaną klasę, przekazać wyszykowane obiekty kontekstowe i wywołać Execute(). Ponieważ masz drzewo CodeDOM dla strony (gdy korzystasz z mechanizmu Razor), możesz nawet dostosować klasę podstawową tak, aby zamiast System.Web.Mvc.WebViewPage dziedziczyła od klasy strony Test, która pozwala zamiana obiektów kontekstu zamiennego, itp.

+4

Dzięki za to - to nie robi Dźwięk brzmi niemal tak prosto, jak mi się zdawało, że uwierzyłem :(Poświęcam mu trochę czasu Soudns może potrzebować cierpliwości i czekać na nowe wydanie Razor. – dextermixwith

+0

Zgadzam się, że to nie jest całkiem proste Jednak wydaje mi się, że Brzytwa radykalnie poprawia zdolność ludzi do pisania uprzęży testowych, które faktycznie mogą uruchomić stronę widoku Razor bez ładowania się ASP.Net (chociaż musisz wyłudzić elementy z frameworka, takie jak HTTP Context i inne rzeczy ASP.Net, których dotyka twój widok). –

+0

Nie spodziewałam się, że będę musiał skompilować kod w pamięci w locie, aby uruchomić Maszynę, ale to działa. – mfloryan

0

Pisałem o poglądach na temat testowania maszyn Razor. Jest brzydki i nieprzyjemny, ale działa i mogłem go zaadaptować, aby przetestować wszystkie moje poglądy we wszystkich projektach.

http://httputility.com/articles/unit-testing-razor-views.html

Chociaż długo żyli projektów Proponuję czeka na uprzęży testu wykonanego przez zespół MVC.

Powiązane problemy