一个单元如何测试实际使用扩展方法中的帮助器的HtmlHelper

时间:2013-03-17 05:47:17

标签: asp.net-mvc-3 unit-testing moq

今天下午我花了更好的时间试图弄清楚如何模拟(使用MOQ)相关的点点滴滴来对下面的HtmlHelper进行单元测试,用户在UrlHelper类中创建img标签:

    public static IHtmlString Image(this HtmlHelper helper, string id, string url, string alternateText, object htmlAttributes)
    {
        // Instantiate a UrlHelper
        var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);

        // Create tag builder
        var builder = new TagBuilder("img");

        // Create valid id
        builder.GenerateId(id);

        // Add attributes
        builder.MergeAttribute("src", urlHelper.Content(url));
        builder.MergeAttribute("alt", alternateText);
        builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));

        // Render tag
        return new MvcHtmlString(builder.ToString(TagRenderMode.SelfClosing));
    }

有没有人在他们的工作中解决过这个问题?

2 个答案:

答案 0 :(得分:1)

您应该测试最终结果。如果你知道你的助手应该重新出现类似的话,那就说:

<img src="test.jpg" id="testId" alt="something" />

然后你的断言应该是通过将这个字符串与实际结果进行比较。你不应该在意它是否在内部使用帮助器。

答案 1 :(得分:1)

当我遇到非单元测试友好的.NET类型时,我通常编写自己的接口(只有我需要的方法)和实现接口的shim类,它只是将方法/属性调用转发给原始类。垫片可通过检查测试。

然后我编写了针对此接口进行单元测试所需的所有代码(因此我依赖于抽象,而不是具体结果)。这包括扩展方法,它扩展了接口而不是原始的具体类型。在这方面,测试扩展方法就像new Mock<IHtmlHelper>() ...一样简单 - 你可以让IHtmlHelper做任何你喜欢的事情,因为你可以在单元测试中完全控制它的行为。

键入接口和垫片对于具有较大接口的类来说有点乏味,但大多数情况下我发现开销非常低。这也意味着我最终会做更少的奇怪技巧来使事情变得可测试,因此我的代码更加一致且易于遵循(依赖性总是以相同的方式注入,测试总是以相同的方式编写)。

我认为Husein Roncevic正在做的一点是,你应该在可观察状态而不是行为方面测试HtmlHelper客户。换句话说,客户端代码的单元测试不应该知道调用了哪些方法(扩展方法或其他方法)。听起来你想对扩展方法本身进行单元测试,这是一件非常合理的事情。