【问题标题】:Testing HtmlHelpers in ASP.NET MVC在 ASP.NET MVC 中测试 HtmlHelper
【发布时间】:2010-09-21 06:21:13
【问题描述】:

有没有办法(单元)测试我自己的 HtmlHelpers?如果我想要自定义控件(由 HtmlHelper 呈现)并且我知道该控件的要求,我该如何先编写测试 - 然后编写代码?有没有特定的(好的)方法可以做到这一点?

值得吗?

【问题讨论】:

    标签: .net asp.net-mvc unit-testing html-helper


    【解决方案1】:

    主要问题是您必须模拟 HtmlHelper,因为您可能正在使用帮助程序的方法来获取路由或值或返回另一个扩展方法的结果。 HtmlHelper 类有很多属性,其中一些非常复杂,例如 ViewContext 或当前的 Controller。

    This post from Ben Hart 解释了如何使用 Moq 创建这样的模拟。可以轻松转换为另一个模拟框架。

    这是我的 Rhino Mocks 版本适应了 MVC 框架的变化。它尚未经过全面测试,但对我有用,但不要指望完美的结果:

        public static HtmlHelper CreateHtmlHelper(ViewDataDictionary viewData)
        {
            var mocks = new MockRepository();
    
            var cc = mocks.DynamicMock<ControllerContext>(
                mocks.DynamicMock<HttpContextBase>(),
                new RouteData(),
                mocks.DynamicMock<ControllerBase>());
    
            var mockViewContext = mocks.DynamicMock<ViewContext>(
                cc,
                mocks.DynamicMock<IView>(),
                viewData,
                new TempDataDictionary());
    
            var mockViewDataContainer = mocks.DynamicMock<IViewDataContainer>();
    
            mockViewDataContainer.Expect(v => v.ViewData).Return(viewData);
    
            return new HtmlHelper(mockViewContext, mockViewDataContainer);
        }
    

    【讨论】:

    • 遗憾的是博客帖子错误,但上面很好地解释了您需要做什么
    • 看起来他们已经稍微改变了 MVC 框架,因为 ViewContext 现在也需要一个 TextWriter
    • 这非常有用,但是针对 MVC3 进行测试时,我必须通过向 mockViewContextConstructor 添加一个新参数(我使用 TextWriter.Null)来调整它,而不是 mockViewDataContainer,我必须显式设置 ViewData(例如,mockViewDataContainer.ViewData = viewData;) 或 Rhino Mocks 会抛出异常。
    • 有没有人测试过一个叫做 htmlhelper.partial 的辅助方法?一切正常,直到它调用它,然后抛出一些错误,这与需要用 tempdata 返回一些东西有关。为什么他们让这些东西如此难以测试?
    【解决方案2】:

    如果有人正在寻找如何创建 HtmlHelper&lt;T&gt;(这就是我所追求的),这里有一个可能会有所帮助的实现 - 我的类型是一个名为 Model 的类:

    public static HtmlHelper<Model> CreateHtmlHelper()
    {
        ViewDataDictionary vd = new ViewDataDictionary(new Model());
    
        var controllerContext = new ControllerContext(new Mock<HttpContextBase>().Object,
                                                      new RouteData(),
                                                      new Mock<ControllerBase>().Object);
    
        var viewContext = new ViewContext(controllerContext, new Mock<IView>().Object, vd, new TempDataDictionary(), new Mock<TextWriter>().Object);
    
        var mockViewDataContainer = new Mock<IViewDataContainer>();
        mockViewDataContainer.Setup(v => v.ViewData).Returns(vd);
    
        return new HtmlHelper<Model>(viewContext, mockViewDataContainer.Object);
    }
    

    或者更通用的实现:

        public HtmlHelper<T> CreateHtmlHelper<T>() where T : new()
        {
            var vd = new ViewDataDictionary(new T());
    
            var controllerContext = new ControllerContext(new Mock<HttpContextBase>().Object,
                                                          new RouteData(),
                                                          new Mock<ControllerBase>().Object);
    
            var viewContext = new ViewContext(controllerContext, new Mock<IView>().Object, vd, new TempDataDictionary(), new Mock<TextWriter>().Object);
    
            var mockViewDataContainer = new Mock<IViewDataContainer>();
            mockViewDataContainer.Setup(v => v.ViewData).Returns(vd);
    
            return new HtmlHelper<T>(viewContext, mockViewDataContainer.Object);
        }
    

    【讨论】:

      【解决方案3】:

      我正在创建一个自定义助手,这是我用来模拟带有 Moq 和 ASP MVC 2 的 httphelper 的代码。我还将作为参数传递一个 HttpRequestBase 的模拟。如果你不需要它,你可以删除它

      公共静态 HtmlHelper CreateHtmlHelper(ViewDataDictionary viewData, Mock requestMock) { var contextBaseMock = new Mock(); contextBaseMock.SetupGet(cb => cb.Request).Returns(requestMock.Object); var cc = new ControllerContext(contextBaseMock.Object, 新的路线数据(), 新的 Mock().Object); var vctx = 新的 ViewContext( 抄送, 新的 Mock().Object, 视图数据, 新的 TempDataDictionary(), 新 HtmlTextWriter(新 StreamWriter(新 MemoryStream()))); var mockViewDataContainer = new Mock(); mockViewDataContainer.SetupGet(v => v.ViewData).Returns(viewData); 返回新的 HtmlHelper(vctx, mockViewDataContainer.Object); }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-15
        • 2023-03-25
        • 1970-01-01
        • 2011-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-30
        相关资源
        最近更新 更多