获取View View Name,其中ViewResult.ViewName为单元测试的空字符串

时间:2011-11-28 20:19:33

标签: asp.net-mvc asp.net-mvc-3 unit-testing

我在ActionResult上编写了一个扩展方法,用于单元测试,它将断言ViewName返回的是否是预期的。这是我到目前为止的代码:

public static void AssertViewWasReturned(this ActionResult result, string viewName)
{
    string actualViewName;

    if (result is ViewResult)
        actualViewName = (result as ViewResult).ViewName;
    else if (result is PartialViewResult)
        actualViewName = (result as PartialViewResult).ViewName;
    else
        throw new InvalidOperationException("Results of type " + result.GetType() + " don't have a ViewName");

    Assert.AreEqual(viewName, actualViewName, string.Format("Expected a View named{0}, got a View named {1}", viewName, actualViewName));
}

这种方法很好,除非控制器在没有指定名称的情况下返回视图 - 在这种情况下result.ViewName是一个空字符串。

所以,我的问题是 - 从ViewResult对象那里告诉我ViewName的名称是什么,ViewName是一个空字符串吗?

6 个答案:

答案 0 :(得分:6)

如果未通过MVC管道调用您的控制器方法,则不会向Controller.ViewData字典添加其他信息(我假设它会以某种方式提供“操作”-key,但无法确认)。但是,由于您在路由框架的上下文“外部”使用控制器,因此无法知道被调用的方法。

所以答案就是“不”。如果未指定视图的名称,则无法从操作返回的ViewResult中确定它。至少不是你的控制器的测试方式(顺便说一句,这完全没问题)。

答案 1 :(得分:4)

对于它的价值 - 我已经修改了我的测试我的扩展方法(包含J. Tihon的反馈):

public static void AssertViewWasReturned(this ActionResult result, string viewName, string defaultViewName)
{    
    Assert.IsInstanceOf<ViewResultBase>(result, "Result is not an instance of ViewResultBase");
    var viewResult = (ViewResultBase)result;

    var actualViewName = viewResult.ViewName;

    if (actualViewName == "")
        actualViewName = defaultViewName;

    Assert.AreEqual(viewName, actualViewName, string.Format("Expected a View named{0}, got a View named {1}", viewName, actualViewName));
}

这意味着我的单元测试可以包含这样的代码:

var result = controller.MyAction();
result.AssertViewWasReturned("ExpectedViewName","MyAction")

它不如我所希望的那样好,因为我需要指定'defaultViewName'(即动作名称),但这是一个合理的比较。

答案 2 :(得分:2)

您可以更新控制器以始终传递所需的视图。

而不是:

public ActionResult Index()
{
    return View();
}

请改为:

public ActionResult Index()
{
    return View("Index");
}

要么改变你的单位测试代码。

答案 3 :(得分:1)

不确定我是否理解您的问题,但如果调用View()方法时没有参数,MVC将在名为Controller的目录中查找具有调用操作方法名称的View(不带“Controller”后缀添加到名称上。)

例如,这个动作:

public class UserController : Controller
{
    public ActionResult SomeAction()
    {
        // some code here
        return View();
    }
}

因为这是一个空的View()调用,MVC将查找路径和文件名为~\Views\User\SomeAction.cshtml的视图。

这会回答你的问题吗?

答案 4 :(得分:1)

您必须在返回时调用您的视图名称。

前:

Public ActionResult Index(){

// your code

Return View("YourViewName", DataToSendForView);
}

答案 5 :(得分:0)

您可以覆盖控制器。 OnResultExecuted方法是控制器生命周期中有可用视图的点。

protected override void OnResultExecuted(ResultExecutedContext ctx)
{
    base.OnResultExecuted(ctx);
    String ViewPath = ((System.Web.Mvc.BuildManagerCompiledView)((System.Web.Mvc.ViewResultBase)ctx.Result).View).ViewPath.ToString();
}