【问题标题】:How can I unit test an MVC UserViewControl?如何对 MVC UserViewControl 进行单元测试?
【发布时间】:2008-10-23 10:03:44
【问题描述】:

我一直在尝试为 ASP.NET MVC 中的 UserViewControl 编写单元测试。我想编写如下所示的代码:

[TestMethod]
public void HaveControlToDisplayThings()
{
    var listControl = new ControlUnderTest();
    var viewData = new ViewDataDictionary<IList<string>>(this.repo.GetMeSomeData());

    // Set up a ViewContext using Moq.
    listControl.SetFakeViewContext(viewData);
    listControl.ViewData = viewData;
    listControl.RenderView(listControl.ViewContext);

    // Never got this far, no idea if this will work :)
    string s = listControl.ViewContext.HttpContext.Response.Output.ToString();
    Assert.AreNotEqual(0, s.Length);
    foreach (var item in this.repo.GetMeSomeData())
    {
        Assert.IsTrue(s.IndexOf(item) != -1);
    }
}

不幸的是,无论我尝试什么,我都会从 RenderView 深处得到错误。这是由静态 HttpContext.Current 对象无用引起的(据我所知) - 我从 System.Web.UI.Page.SetIntrinsics 得到 NullReferenceExceptions。

我尝试使用 Phil Haack 的 HttpSimulator,它给了我一个 HttpContext 对象,但我发现我还需要指定一个假的 HttpBrowserCapabilities 对象才能稍微进一步:

Subtext.TestLibrary.HttpSimulator simulator = new HttpSimulator();
simulator.SimulateRequest();
var browserMock = new Mock<HttpBrowserCapabilities>();
browserMock.Expect(b => b.PreferredRenderingMime).Returns("text/html");
browserMock.Expect(b => b.PreferredResponseEncoding).Returns("UTF-8");
browserMock.Expect(b => b.PreferredRequestEncoding).Returns("UTF-8");
HttpContext.Current.Request.Browser = browserMock.Object;

现在我得到了对该对象的属性访问异常。我尽可能多地嘲笑,但似乎无处可去。

有人设法完成这项工作吗?

【问题讨论】:

  • 我很久以前就放弃了对视图的单元测试。尝试将您拥有的任何业务逻辑移动到控制器中,然后对它们进行单元测试。视图对于单元测试来说是出了名的复杂。可能会有一个真正的答案,但我不久前就放弃了,因为我们的观点发展得太快了。
  • 是的,一般来说我不想测试我的视图,但是当我使用用户控件时,这是一个可重复使用的部分,经常在整个应用程序中使用并且没有控制器代码可以说。我想测试它是否可以被实例化和渲染并且包含大致正确的东西。
  • 据我了解,您实际上是在测试 repo.GetMeSomeData() ,它不依赖于视图或用户控制。你能检查一下 repo.GetMeSomeData() 是否给了你想要的东西而不是调用控件吗?
  • 嗨,我知道 GetMeSomeData 正在工作,因为它是独立测试的,我要测试的是来自该调用的数据是否在 HTML 中呈现。

标签: c# asp.net-mvc mocking


【解决方案1】:

不幸的是,ASP.NET 视图引擎在 ASP.NET 宿主环境中使用了 VirtualPathProvider。更糟糕的是,我使用 Reflector 跟踪了一些其他代码,发现对 VirtualPath 实用程序的一些硬代码引用存在其他依赖关系。 我希望他们在版本中解决这个问题,这样我们就可以真正测试我们的视图以及它们是如何呈现的。

【讨论】:

  • 接受这个作为答案,因为它似乎本质上是:不,没有办法单元测试呈现视图的结果。使用 selenium、Watin 或同等产品是一个不错的选择,但这不是我真正想做的 - 控制/视图输出的无浏览器测试。
【解决方案2】:

一种选择是在浏览器中运行单元测试。对于这种情况,我使用Selenium 取得了成功。

【讨论】:

    【解决方案3】:

    我们放弃了单元测试视图,现在将 WatiN 浏览器测试作为我们构建的一部分。

    我们还使用 Resharper 解决方案范围分析来检查是否存在编译器错误。不完美,但它得到了非常相似的结果。缺点 - WatiN 测试很慢。

    【讨论】:

      【解决方案4】:

      这些是需要在 HttpBrowserCapabilities 对象中设置才能运行 asp.net webforms 站点的值,我会尝试确保这些值已设置,看看是否能解决您的问题,我不确定是否会但是,嘿,值得一试吗?

      • 浏览器(又名)
      • useragent(在请求中传递)
      • 表格(真/假)
      • 版本(浏览器版本,例如 1.0)
      • w3cdomversion(例如 1.0)
      • cookies(真/假)
      • ecmascript 版本(例如 1.0)

      希望这会有所帮助。

      【讨论】:

      • 谢谢,我会在下次编写该代码时尝试一下。
      【解决方案5】:

      我也推荐selenium 用于 UI 测试。标准 MVC 应用程序中有相当多的内容可以进行单元测试,但 UI 级别的组件似乎更适合 Selenium 等浏览器内测试。您可以使用 cruisecontrol.net 将 Selenium 测试与您的单元测试集成。

      这是一个guide,用于将 Selenium 与您的 CC.Net 集成。

      【讨论】:

        【解决方案6】:

        使用 TypeMock 模拟掉依赖项。我已经写了one blog post 关于如何模拟控制器层中的请求和响应依赖项。也许它有帮助。

        【讨论】:

          猜你喜欢
          • 2011-09-17
          • 2018-02-11
          • 2011-07-27
          • 1970-01-01
          • 2010-10-22
          • 1970-01-01
          • 2012-01-08
          • 2019-11-02
          • 1970-01-01
          相关资源
          最近更新 更多