23

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

这值得吗?

4

3 回答 3

30

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

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);
    }
于 2009-04-14T11:47:24.313 回答
9

如果有人正在寻找如何创建HtmlHelper<T>(这就是我所追求的),这里有一个可能会有所帮助的实现——我的类型是一个名为 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);
    }
于 2011-05-11T00:40:45.173 回答
0

我正在创建一个自定义助手,这是我用来模拟具有 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);
        }
于 2011-02-01T13:54:59.967 回答