2009-07-30 152 views
6

我正在尝试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上的例子,我只是困惑,我需要什么其他的管道,使上述任一第一单元测试例的工作。

干杯,

安德鲁

回答

7

究其原因,测试失败是因为什么决定VIEWNAME当你不指定一个明确是在框架的深处。更确切地说,在视图引擎中我相信。所以为了测试它,你将不得不嘲笑更多的请求管道。

我做什么,并建议,是不依赖于默认值,并指定明确的观点:

return View("About"); 

则该值将在那里没有嘲笑任何测试:

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

Thankyou在看到方法签名之一是View(字符串viewName,对象模型)后,您的观点变得非常有意义!附:测试通过了! :-) – 2009-07-30 14:41:06

3

这是因为你正在假设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让你开始。