如何使用moq模拟控制器上下文

我正在尝试MOQ框架,现在我已经遇到了障碍。 以下unit testing失败,因为ViewName属性的实际值是空字符串。

任何人都可以指出我正确的方向,为什么这不通过测试?

[TestMethod] public void Can_Navigate_To_About_Page() { var request = new Mock(); request.Setup(r => r.HttpMethod).Returns("GET"); var mockHttpContext = new Mock(); mockHttpContext.Setup(c => c.Request).Returns(request.Object); var controllerContext = new ControllerContext(mockHttpContext.Object, new RouteData(), new Mock().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的例子我只是对于我需要做出上述第一个unit testing示例工作的其他管道工作感到困惑。

干杯,

安德鲁

测试失败的原因是因为当您没有明确指定ViewName时,决定ViewName的是在框架的深度。 更确切地说,在视图引擎中我相信。 因此,为了测试它,你将不得不模拟更多的请求管道。

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

 return View("About"); 

然后值将在那里测试而不嘲笑任何东西:

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

这是因为您对MVC框架的工作原理做出了假设。 如果依靠约定来定位视图,框架实际上会将ViewName属性保留为String.Empty直到调用ExecuteResult()为止。

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

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

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

如果你正在寻找一种在MVC中使用模拟的好方法,你可能想看看测试你的路线(这看起来像你在这里尝试做的那样)。 你可以找到Phil Haack关于这个主题的post来帮助你入门。