Необходимы указатели для написания модульного теста для представления на основе Razor - PullRequest
5 голосов
/ 13 августа 2010

Я пробую новый движок Razor view с MVC 3 Preview 1 и очень хотел бы написать простой модульный тест с использованием NUnit / Moq.Я еще не видел примеров того, чтобы это на самом деле было сделано - несмотря на то, что это одна из реальных функций продажи в Razor.

Так что, если у меня есть контроллер, который использует объект DBConext (сначала код CTP EF4) и представление отображает раскрывающийся список на основе списка элементов, предоставленных в модели, загруженной в действии, вызываемом в контроллере, я хотел бы иметь возможность проверить, что элемент содержит элементы, заполненные в нем.

Вот мой контроллер:

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);
    }

}

Вот моя модель:

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; }
}

А вот мой взгляд:

@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>
 }

Тестовый код, который у меня есть до сих порвыглядит следующим образом:

[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"));
    }
}

При запуске теста я просто получаю исключение NullReferenceException.

Любые идеи / указатели и т. д. приветствуются.Мне бы очень хотелось, чтобы это работало, чтобы я мог в будущем использовать TDD для своих представлений.

Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 14 августа 2010

Я бы предложил полностью исключить класс CshtmlViewEngine и запустить двигатель Razor самостоятельно. Я написал сообщение в блоге о компиляции видов Razor вне ASPX здесь: http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of-aspnet.html

В предварительном просмотре 1 MVC3 механизм Razor встроен в System.Web.Mvc и является общедоступным (IIRC), поэтому вы сможете найти все классы, на которые есть ссылки в этом посте / образце, в System.Web.Mvc. длл.

После того, как вы скомпилировали страницу, просто загрузите сгенерированный класс, передайте макетированные объекты контекста и вызовите Execute (). Так как у вас есть дерево CodeDOM для страницы (когда вы используете механизм Razor), вы можете даже настроить базовый класс, чтобы вместо System.Web.Mvc.WebViewPage он наследовал от базового класса тестовой страницы, который позволяет вам замена в контекстных объектах замены и т. д.

0 голосов
/ 09 марта 2011

Я написал о модульном тестировании Razor views.Это уродливо и всякого рода мерзости, но это работает, и я смог адаптировать его для проверки всех своих взглядов во всех проектах.

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

Хотя для долгоживущих проектов япредложил бы подождать тестового жгута, сделанного командой MVC.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...