如何用moq模拟控制器上下文
问题描述:
我正在尝试MOQ框架,现在我已经遇到了障碍。以下单元测试失败,因为ViewName属性的实际值是空字符串。如何用moq模拟控制器上下文
任何人都可以指出我在正确的方向,请问为什么这不通过测试?
[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上的例子,我只是困惑,我需要什么其他的管道,使上述任一第一单元测试例的工作。
干杯,
安德鲁
答
究其原因,测试失败是因为什么决定VIEWNAME当你不指定一个明确是在框架的深处。更确切地说,在视图引擎中我相信。所以为了测试它,你将不得不嘲笑更多的请求管道。
我做什么,并建议,是不依赖于默认值,并指定明确的观点:
return View("About");
则该值将在那里没有嘲笑任何测试:
var controller = new HomeController();
var result = controller.About() as ViewResult;
Assert.AreEqual("About", result.ViewName);
答
这是因为你正在假设MVC框架是如何工作的。如果您依赖约定来查找视图,则框架实际上将ViewName属性保留为String.Empty
,直到调用ExecuteResult()
。
你可以看到的ViewResultBase.ExecuteResult
68行的代码中the MVC source:
if (String.IsNullOrEmpty(ViewName)) {
ViewName = context.RouteData.GetRequiredString("action");
}
此外,你应该小心你正在测试什么。作为一个经验法则,您应该专注于测试您编写的代码,而不是框架的代码。测试以确保正确解析视图名称是对框架本身的单元测试,而不是构建在其上的应用程序。
如果你正在寻找一种在MVC中使用模拟的好方法,你可能需要考虑测试你的路由(看起来像你在这里试图做的那种)。你可以find a post by Phil Haack concerning just this subject让你开始。
Thankyou在看到方法签名之一是View(字符串viewName,对象模型)后,您的观点变得非常有意义!附:测试通过了! :-) – 2009-07-30 14:41:06