Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get View Name where ViewResult.ViewName is empty string for Unit Testing

I have written an extension method on ActionResult for use in unit testing which will assert whether the ViewName returned is what was expected. This is the code I have so far:

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));
}

This works fine except where the controller returns a View without specifying a name - in this case result.ViewName is an empty string.

So, my question is - is there any well of telling from a ViewResult object what the name of the View was where ViewName is an empty string?

like image 368
StanK Avatar asked Nov 28 '11 20:11

StanK


2 Answers

If your controller-method is not called through the MVC pipeline, additional information are not added to the Controller.ViewData dictionary (which I assumed would somehow provide an "action"-key, but couldn't confirm). But since you using your controller "outside" the context of the routing-framework etc. there is no way it knows about the called method.

So the answer is simply "no". If the name of the view was not specified, you cannot determine it from the ViewResult returned by the action. At least not in the way your controller is being tested (which is totally fine by the way).

like image 69
J. Tihon Avatar answered Nov 20 '22 05:11

J. Tihon


For what it's worth - I've revised my test my extension method like this (incorporating J. Tihon's feedback):

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));
}

This means that my unit tests can contain code like this:

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

It's not as good as I'd hoped, as I need to specify the 'defaultViewName' (i.e. the action name) but is a reasonable comprimise.

like image 5
StanK Avatar answered Nov 20 '22 05:11

StanK