Unit testing my controller method results in an empty ViewName?

后端 未结 4 875
情歌与酒
情歌与酒 2020-12-29 21:18

I\'m doing some simple MS unit tests on my standard, nothing special controller.

When I check the ViewName proprty, from the returned ViewResult

相关标签:
4条回答
  • 2020-12-29 21:56

    I personally found the testing facilities provided by MVC2 to be somewhat clumsy. I'm guessing there is something better already extant, but I ended up creating a simple class to test actions. I modeled the interface (the implementation is another story) on a class provided by the excellent open source Java MVC framework Stripes called MockRoundTrip.

    Here is the method used to get the action destination page when testing actions, called getTripDestination(). It returns the correct result irrespective of whether the viewname is explicitly set or not

        //Get the destination page of the request, using Runtime execution pattern of MVC, namely
        //if no ViewName is explicitly set in controller, ViewResult will have an empty ViewName
        //Instead, current action name will be used in its place
        public string getTripDestination()
        {
           RouteData routeData = getRouteData();
           ViewResult viewResult = (result is ViewResult) ? (ViewResult)result : null;
           string tripDestination = (viewResult != null) ? viewResult.ViewName : "";
    
           return (tripDestination != "") ? tripDestination : (String)routeData.Values["action"];
        }
    
        private RouteData getRouteData()
        {
           HttpContextBase context = controller.ControllerContext.RequestContext.HttpContext;
           return RouteTable.Routes.GetRouteData(context);
        }
    
    0 讨论(0)
  • 2020-12-29 22:01

    The documentation for Controller.View() states:

    This method overload of the View class returns a ViewResult object that has an empty ViewName property. If you are writing unit tests for controller actions, take into account the empty ViewName property for unit tests that do not take a string view name.

    At run time, if the ViewName property is empty, the current action name is used in place of the ViewName property.

    So when expecting a view with the same name as the current action we can just test that it's an empty string.

    Alternatively, the Controller.View(String) method will set the ViewName.

    0 讨论(0)
  • 2020-12-29 22:09

    The viewname is set automatically by the framework. But when we unit test, we short-circuit the framework and there is nothing left to set the name.

    So our actions need to set the viewname explicitly when we unit test. We could also check for null or empty if we really, really want to lean on the convention.

    0 讨论(0)
  • 2020-12-29 22:12

    The ViewName is only present when you set it in the ViewResult. If your View name matches your controller name, then I would check to ensure that the ViewName is null or empty as that would be (IMO) the correct behavior since you wouldn't want to set a name on the view. I only check that the ViewName is set when I intend that the View to be returned does not match the action -- say, when returning the "Error" view, for example.

    EDIT: The following is the source for ExecuteResult in ViewResultBase.cs (from RC1, I don't have the source for RTW on my Macintosh). As you can see it checks to see if the ViewName has been set directly and if not, it pulls it from the action in the controller context's route data. This only happens in ExecuteResult, which is invoked AFTER your controller's action has completed.

        public override void ExecuteResult(ControllerContext context) {
            if (context == null) {
                throw new ArgumentNullException("context");
            }
            if (String.IsNullOrEmpty(ViewName)) {
                ViewName = context.RouteData.GetRequiredString("action");
            }
    
            ViewEngineResult result = null;
    
            if (View == null) {
                result = FindView(context);
                View = result.View;
            }
    
            ViewContext viewContext = new ViewContext(context, View, ViewData, TempData);
            View.Render(viewContext, context.HttpContext.Response.Output);
    
            if (result != null) {
                result.ViewEngine.ReleaseView(context, View);
            }
        }
    
    0 讨论(0)
提交回复
热议问题