Unit Tests for MVC3 AsyncController - asp.net-mvc-3

I have read a couple of posts on this topic, but neither addresses my issue directly. When you test a synchronous controller method, you can assert that the method is returning the type you expect:
Assert.IsInstanceOfType(result,typeof(JsonResult));
However, when testing async controller methods, I have only been able to assert that the type returned by the AsyncManager is the correct type:
var result = controller.AsyncManager.Parameters["articles"];
// Assertions
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result,typeof(IEnumerable<NewsArticle>));
Seems to me I should be testing the return type of the Completed method which in my case is a JsonResult:
public JsonResult GetPublishedNewsArticlesCompleted(IEnumerable<NewsArticle> articles)
{
return Json(articles, JsonRequestBehavior.AllowGet);
}
But I haven't been able to figure out how to do this. I read a post by Dino Esposito in which he said that "the code of xxxCompleted is trivial and probably wouldn't even need a test". I am not buying it. The Completed method and it's return type is what I care most about in this test.
So my question is how do I test that my Completed method is actually giving me back a JsonResult? Or is Dino right and I just shouldn't care?
Thanks.

What I have done with my asynchronous methods is to just test the Async method and not the Completed method. My decision to do this is based on the fact that there is no business logic in the Completed method. All it does is serialize my return object and pass it back as Json or Jsonp if it is cross domain. I didn't write it and most folks will tell you if you don't write it, don't test it.

Related

Should I specify an specific ActionResult or use the abstract class in my ASP.NET MVC AJAX methods?

If I have an action method that I know it will only be called via AJAX and always returning JSON...
Do I set the method return type to JsonResult or leave it to ActionResult?
Please explain the reason of the choice.
You should declare your action methods as returning ActionResult, so that they have the freedom to return any concrete result class.
Check this answer: https://stackoverflow.com/a/15250991/7720

Is there an equivalent of the ActionResult RedirectToAction for ViewResult?

I have looked at previous questions but I could not find an answer to this particular scenario: I am using ASP.NET MVC 3 with a TDD approach. On my action methods, I use the return type of ViewResult opposed to ActionResult. This is fine to test my controllers. However, I need to test my view models as well as my controllers. I can do this quite happily by using the Model property on the ViewResultBase (which is implemented ViewResult but not ActionResult) for my model tests.
If there view model is null then I would like to redirect to another action. ActionResult supports a RedirectToAction method. However, ViewResult does not. I have tried the View method but the url does not change in the browser address bar. Also, I even tried the classic ASP.Net Response.Redirect(...), unsurprising, my unit test complains that the Response object has not been populated.
So, what approach do I use to achieve the equivalent of the ActionResult RedirectToAction for ViewResult?
if you need to return more than one result type from a controller, then set its return type to action result and then assert that the different conditions create the right result type.
For instance, in AJAX actions, you may want to return HttpStatusCodeResults to set the response property to errors should validation fail or there be an exception.
Then when the action has succeeded, you may want to return a partial view for display with the result.
Using this approach you can tailor your logic in your controller and still assert the different results are correct.
I found a way to do it. I used the following steps:
I set my action method return type to ActionResult
I changed its unit test to use ActionResult
I created two additional action methods with the return type of ResultView.
For each branch of the if statement of action method from [1], I redirected to the appropriate action method in [3], I used RedirectToAction to redirect.
I create two unit tests that use ResultView to test the action methods created in [3] and give me access to the underlying Model for each.

RESTful design pattern in MVC?

I'm designing an application trying to follow the REST spec. I'm trying to figure out the best way to design it.
So let's say I'm doing a POST call that so I have a "post" method in my controller and model
// in controller
function post()
{
//call post model here
}
In my post request I need to make the following checks:
-validate fields
-make sure item name is unique for that user
-make sure there are less than 10 items
-etc (there could be more cases)
Now in controller post function I will return a REST message and status code based on whatever happens, which is fine, but I'm curious to know where it's better to keep all those checks.
I can put all the checks in the model and then return some kind of array like:
array('text' => 'return response text/array or whatever here', 'code' => '200/400/etc')
Then just return this in the controller, or is it better to break up those checks into individual functions within the model and then do all the checks in the controller?
// in controller
function post()
{
//if validation fails -> send response
//if name is not unique -> send response
//etc...
}
From a design point of view, if I ever wanted to potentially call the "post" method in the project model from other methods, it would not have an all encompassing function to handle it, however if I do keep it all in one model function it doesn't give me a lot of reusability. If I had to pick sides, chances are I probably wouldn't need to reuse those "check functions" too much anyway, however it also seems weird to have all that response info in the model rather than the controller.
Can anyone please give me some input on this.
I would not create post method inside the model (although having it in the controller is perfectly fine) simply because you just put code/model in such a frame that is not re-usable plus less readable. For instance, instead of post method in the model I would create create method.
There is no one-fits-all way for data validation. I like creating validation classes which have only one method validate for various data types (e.g. username validation class checks if it matches regex and is unique). It's better than copy pasting the validation code to every action (DRY). Where to call this class method? It depends. You can simply call that it in the action. Since the validation code is inside the validation class, it will look alright. You can also create a mapper which takes the request, determines what validations have to be performed and etc. but it might be overkill and is hard to do properly (maintainability wise).
For output again - DRY. It depends on what MVC framework are you using and there might be a good solution for this already. If not, you can create a class for that (yup, I am DRY maniac). You pass response code, array (or string) with response and class nicely wraps everything into JSON, XML format. Advantages: if you change then output format then you need to change only in one place.
Also consider using Remote Facade pattern.
Hopefully, you found something useful in this post.
I would separate the API from the MVC application and use Apify

Can anyone explain the purpose and resolution of CA1822 on a Controller Action?

Error CA1822 : Microsoft.Performance : The 'this' parameter (or 'Me'
in Visual Basic) of 'SomeController.AnAction(string, string)' is never
used. Mark the member as static (or Shared in Visual Basic) or use
'this'/'Me' in the method body or at least one property accessor, if
appropriate.
A static action yields 404 not found when requested via URL. The action is working as expected with code analysis turned off. What's the point of this and what's the appropriate remedy?
Note that the return type of the action is PartialViewResult, it doesn't seem as though code analysis complains about this if the return type is ActionResult.
[HttpPost]
public PartialViewResult BlankEditorRow(string formId, Common.Entities.Common.ObjTypeEnum objType)
{
if (objType == Common.Entities.Common.ObjTypeEnum.Regular)
return new AjaxPartialViewResult("_RowEditor", new ProcedureEntryEntity()) { UpdateValidationForFormId = formId };
else
return new AjaxPartialViewResult("_TemplateRowEditor", new ProcedureEntryEntity()) { UpdateValidationForFormId = formId };
}
Update: Looks like changing the return type to ActionResult resolves the error, and PartialViewResult is an ActionResult so it should work.
I doubt that changing the return type without calling using any instance members really resolves the problem. I suspect that in order to change the return type, you changed the return statement to something which accessed an instance member.
Now I don't know whether the route handling in MVC will let you mark the method as static, but it's worth investigating. Even though the warning is given in terms of performance, I would think of it in terms of intent and readability.
Typically there are two reasons for a method or property to be an instance member (rather than static):
It needs to access another instance member, because the way it behaves depends on the state of the object
It needs to behave polymorphically based on the actual type of the instance it's called on, so that the behaviour can be overridden
If neither of these is the case, then the method can be made static which indicates that there's no polymorphism expected and no instance state required. A static member effectively advertises that the only state it depends upon is the state of the type itself (and the parameters), and that it won't behave polymorphically. Aside from anything else, that means you can test it without creating an instance at all, too.
Of course, if MVC's infrastructure requires it to be an instance method, then you should just suppress the warning, with a comment to indicate that fact.
I think CA just does not take into account that this is a controller action in MVC app. I would suppress.

How to test HtmlHelpers that call Partial?

I've been looking at this Stackoverflow question and have the answer implemented. It works all fine and dandy until I get to call HtmlHelper.Partial in my helper method, which is listed below. I know it might not be the best code, but this is until I can refactor more of the app. The error it throws is
Previous method 'ViewContext.get_TempData();' requires a return value or an exception to throw.
Am I missing mocking something, or is there a better way to render a usercontrol?
Edit Ok I did miss something, I didn't call mocks.Replay(). Now have another error which it wants something named controller in routeData...progress.
Edit #2 Clarifying I'm trying to mock the call to HtmlHelper.Partial(partialPath, model), I just want that to return whatever partialPath I send in I suppose, or at least not blowup. I did find this page http://andrevianna.com/blog/?p=8 which was very helpful and I almost got things working. This was helpful as well http://farm-fresh-code.blogspot.com/2009/10/mocking-htmlhelper-class-with.html
public static string RenderRateDetails(this HtmlHelper html, string partialPath, RatesViewData model, RateDetailType type)
{
switch (type)
{
case RateDetailType.AR:
if (model.ExistingRateDetailAR != null)
return html.Partial(partialPath, model).ToString();
break;
case RateDetailType.AP:
if (model.ExistingRateDetail != null)
return html.Partial(partialPath, model).ToString();
break;
}
return string.Empty;
}
I think the example given at 'farm fresh code' is the right way to go, you can't directly mock the HtmlHelper, but you can build an instance where all of it's dependencies are mocked.
When you're code calls html.Partial(partialPath, model).ToString(), the HtmlHelper calls properties and methods on the dependencies that you mocked, and you get errors if these don't return reasonable default values.
In this case it looks like the TemplateData property of the mocked ViewContext object was called, and I imagine it returned null, hence:
Previous method 'ViewContext.get_TempData();' requires a return value or an exception to throw.
Once you mock this property, you should be able to get past this error, but you might need to mock a few more things before you get it all working.
It might save you some time to take a look at the MVC source code to see what gets called in the Partial method. You can get that here http://aspnet.codeplex.com/releases/view/58781.
EDIT
BTW. The TempData property returns a System.Web.Mvc.TempDataDictionary. Mocking the property to return an empty instance of one of those should solve the immediate problem.
Have you considered using Display and Editor templates for your user controls rather than extending HtmlHelper?
I used to do the same thing quite a lot in the early MVC versions, but I have switched almost completely to using templates now.

Resources