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?
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With