加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 用于为基于Razor的View编写单元测试的指针

发布时间:2020-12-16 03:19:40 所属栏目:asp.Net 来源:网络整理
导读:我正在尝试使用MVC 3 Preview 1的新Razor视图引擎,并且真的想用NUnit / Moq编写一个简单的单元测试.我还没有看到任何实际的例子 – 尽管它是Razor真正的销售功能之一. 因此,如果我有一个使用DBConext对象的Controller(首先是EF4 CTP代码),并且视图根据控制器
我正在尝试使用MVC 3 Preview 1的新Razor视图引擎,并且真的想用NUnit / Moq编写一个简单的单元测试.我还没有看到任何实际的例子 – 尽管它是Razor真正的销售功能之一.

因此,如果我有一个使用DBConext对象的Controller(首先是EF4 CTP代码),并且视图根据控制器上调用的动作中加载的模型中提供的项目列表呈现下拉列表,我会喜欢能够测试该元素是否填充了其中的项目.

这是我的控制器:

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.

提前致谢!

解决方法

我建议完全避免使用CshtmlViewEngine类并自己启动Razor引擎.我写了一篇关于在ASPX之外编译Razor视图的博客文章: http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of-aspnet.html

在MVC3的预览1中,Razor引擎嵌入在System.Web.Mvc中并且是公共的(IIRC),因此您应该能够在System.Web.Mvc.dll中找到该帖子/示例中引用的所有类.

编译完页面后,只需加载生成的类,传入模拟的上下文对象,然后调用Execute().由于你有一个页面的CodeDOM树(当你使用Razor引擎时),你甚至可以调整基类,以便它不是System.Web.Mvc.WebViewPage,它继承了一个Test页面基类,它可以让你交换替换上下文对象等

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读