6

我正在尝试最小起订量框架,现在我遇到了障碍。以下单元测试失败,因为 ViewName 属性的实际值为空字符串。

谁能指出我正确的方向,为什么这没有通过测试?

[TestMethod]
public void Can_Navigate_To_About_Page()
{
    var request = new Mock<HttpRequestBase>();
    request.Setup(r => r.HttpMethod).Returns("GET");
    var mockHttpContext = new Mock<HttpContextBase>();
    mockHttpContext.Setup(c => c.Request).Returns(request.Object);

    var controllerContext = new ControllerContext(mockHttpContext.Object, 
                                new RouteData(), 
                                new Mock<ControllerBase>().Object);
    var controller = new HomeController();

    controller.ControllerContext = controllerContext;
    var result = controller.About() as ViewResult;

    Assert.AreEqual("About", result.ViewName);
}

下面还会产生一个空的 ViewName。

        HomeController controller = new HomeController();
        ViewResult result = controller.About() as ViewResult;
        Assert.IsNotNull(result);
        Assert.AreEqual("About", result.ViewName);

从网络上演示模拟和良好 TTD 的示例来看,我只是对要使上述第一个单元测试示例工作所需的其他管道感到困惑。

干杯,

安德鲁

4

2 回答 2

7

测试失败的原因是,当您没有明确指定 ViewName 时,决定 ViewName 的是框架的深处。更准确地说,在我相信的视图引擎中。因此,要按现状进行测试,您将不得不模拟出更多的请求管道。

我所做的并建议不要依赖默认值并明确指定视图:

return View("About");

然后该值将在那里进行测试而无需模拟任何东西:

var controller = new HomeController();
var result = controller.About() as ViewResult;
Assert.AreEqual("About", result.ViewName);
于 2009-07-30T14:37:40.810 回答
3

这是因为您正在对 MVC 框架的工作方式做出假设。如果您依赖约定来定位视图,则框架实际上将 ViewName 属性保留为String.Empty直到ExecuteResult()被调用。

ViewResultBase.ExecuteResult您可以在MVC 源代码的第 68 行看到此代码:

if (String.IsNullOrEmpty(ViewName)) {
   ViewName = context.RouteData.GetRequiredString("action");
}

此外,您应该小心您正在测试的内容。根据经验,您应该专注于测试您编写的代码,而不是框架的代码。确保按惯例正确解析视图名称的测试实际上是对框架本身的单元测试,而不是构建在其上的应用程序。

如果您正在寻找一种在 MVC 中使用模拟的好方法,您可能需要查看测试您的路线(这看起来就像您在这里尝试做的那样)。您可以找到 Phil Haack 发表的关于此主题的帖子,以帮助您入门。

于 2009-07-30T14:47:33.633 回答