Is it really necessary to test controller methods? - asp.net-mvc

When I design MVC apps, I typcially try to keep almost all logic (as much as possible) out of my app. I try to abstact this into a service layer which interfaces with my repositories and domain entities.
So, my controller methods end up looking something like this:
public ActionResult Index(int id)
{
return View(Mapper.Map<User, UserModel>(_userService.GetUser(id)));
}
So assuming that I have good coverage testing my services, and my action methods are simple like the above example, is it overkill to unit test these controller methods?
If you do build unit tests for methods that look like this, what value are you getting from your tests?

If you do build unit tests for methods that look like this, what value
are you getting from your tests?
You can have unit tests that assert:
That the GetUser method of the _userService was invoked, passing the same int that was passed to the controller.
That the result returned was a ViewResult, instead of a PartialViewResult or something else.
That the result's model is a UserModel instance, not a User instance (which is what gets returned from the service).
Unit tests are as much a help in refactoring as asserting the correctness of the application. Helps you ensure that the results remain the same even after you change the code.
For example, say you had a change come in that the action should return a PartialView or JsonResult when the request is async/ajax. It wouldn't be much code to change in the controller, but your unit tests would probably fail as soon as you changed the code, because it's likely that you didn't mock the controller's context to indicate whether or not the request is ajax. So this then tells you to expand on your unit tests to maintain the assertions of correctness.
Definitely value added IMO for 3 very simple methods which shouldn't take you longer than a couple of minutes each to write.

Related

Understanding Mock Unit Testing

am trying to understand using Mock unit testing and i started with MOQ . this question can be answered in General as well.
Am just trying to reuse the code given in How to setup a simple Unit Test with Moq?
[TestInitialize]
public void TestInit() {
//Arrange.
List<string> theList = new List<string>();
theList.Add("test3");
theList.Add("test1");
theList.Add("test2");
_mockRepository = new Mock<IRepository>();
//The line below returns a null reference...
_mockRepository.Setup(s => s.list()).Returns(theList);
_service = new Service(_mockRepository.Object);
}
[TestMethod]
public void my_test()
{
//Act.
var myList = _service.AllItems();
Assert.IsNotNull(myList, "myList is null.");
//Assert.
Assert.AreEqual(3, myList.Count());
}
Here is my question
1 . In testInitialize we are setting theList count to 3(string) and we are returning the same using MOQ and in the below line we are going to get the same
var myList = _service.AllItems(); //Which we know will return 3
So what we are testing here ?
2 . what are the possible scenarios where the Unit Testing fails ? yes we can give wrong values as 4 and fail the test. But in realtime i dont see any possiblity of failing ?
i guess am little backward in understanding these concepts. I do understand the code but am trying to get the insights !! Hope somebody can help me !
The system under test (SUT) in your example is the Service class. Naturally, the field _service uses the true implementation and not a mock. The method tested here is AllItems, do not confuse with the list() method of IRepository. This latter interface is a dependency of your SUT Service therefore it is mocked and passed to the Service class via constructor. I think you are confused by the fact that AllItems method seems to only return the call from list() method of its dependency IRepository. Hence, there is not a lot of logic involved there. Maybe, reconsider this example and add more expected logic for the AllItems method. For example you may assert that the AllItems returns the same elements provided by the list() method but reordered.
I hope I can help you with this one.
1.) As for this one, your basically testing he count. Sometimes in a collection, the data accumulates so it doesn't necessarily mean that each time you exectue the code is always 3. The next time you run, it adds 3 so it becomes 6 then 9 and so on.
2.) For unit testing, there are a lot of ways to fail like wrong computations, arithmetic overflow errors and such. Here's a good article.
The test is supposed to verify that the Service talks to its Repository correctly. We do this by setting up the mock Repository to return a canned answer that is easy to verify. However, with the test as it is now :
Service could perfectly return any list of 3 made-up strings without communicating with the Repository and the test would still pass. Suggestion : use Verify() on the mock to check that list() was really called.
3 is basically a magic number here. Changes to theList could put that number out of sync and break the test. Suggestion : use theList.Count instead of 3. Better : instead of checking the number of elements in the list, verify that AllItems() returns exactly what was passed to it by the Repository. You can use a CollectionAssert for that.
This means getting theList and _mockRepository out of TestInit() to make them accessible in a wider scope or directly inside the TestMethod, which is probably better anyways (not much use having a TestInitialize here).
The test would fail if the Service somehow stopped talking to its Repository, if it stopped returning exactly what the Repository gives it, or if the Repository's contract changed. More importantly, it wouldn't fail if there was a bug in the real implementation for IRepository - testing small units allows you to point your finger at the exact object that is failing and not its neighbors.

ASP.NET MVC and IoC - Chaining Injection

Please be gentle, I'm a newb to this IoC/MVC thing but I am trying. I understand the value of DI for testing purposes and how IoC resolves dependencies at run-time and have been through several examples that make sense for your standard CRUD operations...
I'm starting a new project and cannot come up with a clean way to accomplish user permissions. My website is mostly secured with any pages with functionality (except signup, FAQ, about us, etc) behind a login. I have a custom identity that has several extra properties which control access to data... So....
Using Ninject, I've bound a concrete type* to a method (Bind<MyIdentity>().ToMethod(c => MyIdentity.GetIdentity()); so that when I add MyIdentity to a constructor, it is injected based on the results of the method call.
That all works well. Is it appropriate to (from the GetIdentity() method) directly query the request cookies object (via FormsAuthentication)? In testing the controllers, I can pass in an identity, but the GetIdentity() method will be essentially untestable...
Also, in the GetIdentity() method, I will query the database. Should I manually create a concrete instance of a repository?
Or is there a better way all together?
I think you are reasonably on the right track, since you abstracted away database communication and ASP.NET dependencies from your unit tests. Don't worry that you can't test everything in your tests. There will always be lines of code in your application that are untestable. The GetIdentity is a good example. Somewhere in your application you need to communicate with framework specific API and this code can not be covered by your unit tests.
There might still be room for improvement though. While an untested GetIdentity isn't a problem, the fact that it is actually callable by the application. It just hangs there, waiting for someone to accidentally call it. So why not abstract the creation of identities. For instance, create an abstract factory that knows how to get the right identity for the current context. You can inject this factory, instead of injecting the identity itself. This allows you to have an implementation defined near the application's composition root and outside reach of the rest of the application. Besides that, the code communicates more clearly what is happening. Nobody has to ask "which identity do I actually get?", because it will be clear by the method on the factory they call.
Here's an example:
public interface IIdentityProvider
{
// Bit verbose, but veeeery clear,
// but pick another name if you like,
MyIdentity GetIdentityForCurrentUser();
}
In your composition root you can have an implementation of this:
private sealed class AspNetIdentityProvider : IIdentityProvider
{
public MyIdentity GetIdentityForCurrentUser()
{
// here the code of the MyIdentity.GetIdentity() method.
}
}
As a trick I sometimes have my test objects implement both the factory and product, just for convenience during unit tesing. For instance:
private sealed class FakeMyIdentity
: FakeMyIdentity, IIdentityProvider
{
public MyIdentity GetIdentityForCurrentUser()
{
// just returning itself.
return this;
}
}
This way you can just inject a FakeMyIdentity in a constructor that expects an IIdentityProvider. I found out that this doesn’t sacrifice readability of the tests (which is important).
Of course you want to have as little code as possible in the AspNetIdentityProvider, because you can't test it (automatically). Also make sure that your MyIdentity class doesn't have any dependency on any framework specific parts. If so you need to abstract that as well.
I hope this makes sense.
There are two things I'd kinda do differently here...
I'd use a custom IPrincipal object with all the properties required for your authentication needs. Then I'd use that in conjunction with custom cookie creation and the AuthenticateRequest event to avoid database calls on every request.
If my IPrincipal / Identity was required inside another class, I'd pass it as a method parameter rather than have it as a dependency on the class it's self.
When going down this route I use custom model binders so they are then parameters to my actions rather than magically appearing inside my action methods.
NOTE: This is just the way I've been doing things, so take with a grain of salt.
Sorry, this probably throws up more questions than answers. Feel free to ask more questions about my approach.

Test-driven development with ASP.NET MVC - where to begin?

I've read a lot about Test-Driven Development (TDD) and I find the principles very compelling, based on personal experience.
At the moment I'm developing a website for a start-up project I'm involved in, and I'd like to try my hand at putting TDD into practice.
So ... I create a blank solution in Visual Studio 2010, add an ASP.NET MVC Website project and a test project.
I also add a class library called 'Domain', for my domain objects, and a test project for that.
Now I'm wondering where to begin. Should I be writing a test before I do anything right? The question is - should I start writing tests for domain objects? If so, what exactly should I be testing for, since the domain objects don't yet exist?
Or should I be starting with the Website project and writing tests for that? If so, what should I write a test for? The Home controller / Index action?
I typically start by collecting a set of stories for the application I'm going to develop. From that I generate a domain model, usually on "paper". I organize the stories that I'm going to implement and start creating the domain model in the DB for the first set of stories.
Once I have the initial DB, then I use an ORM, in my case, LINQ to SQL, to map the DB tables onto a set of initial classes. I don't typically unit test generated code so this gives me a fair amount of code as a base to start with. I then create a stub method, which throws a not implemented exception, to implement one feature of the first domain class I'm working with. Typically, I start with validation logic. Once you have your stub method, then you can use the VS right click menus to create one or more unit tests for that method. Then you're on your way.
Once I've finished with the domain objects for the first story, I then start working with the MVC aspects. First, I'll create the view models for the first view. These are typically just an empty container class as this point. Then I'll create the view and strongly type it to the view model. I'll start fleshing out the view, adding properties to the view model as needed by the view. Note that since the view model is simply a container there aren't typically unit tests associated with it. It will however be used in subsequent controller tests.
Once the view is complete (or at least my initial concept is complete), I then create the stub controller action or actions for it, again the stub method simply throws a not implemented exception. This is enough to get it to compile and let me use the tools to create unit tests for it. I proceed as needed to test the method(s) and ensure that it acts appropriately to the given inputs and produces an appropriate view model. If the method can produce multiple view models, i.e., render multiple views I may iterate over the process of creating view models/views/controller code until the story or stories are complete.
Repeat as necessary until your set of stories are implemented, refactoring along the way.
Writing unit tests before even declaring the class you are testing seems a little extreme in a static languages such as C#. So you start by declaring your domain classes, throw a few interfaces that define operations you will perform on these domain objects and then you add a class that will implement an interface, leaving methods just throw NotImplementedException. At that moment you could write a unit test for this class, as all the types are known. You run the test which will fail, then you implement the method and run the test again - it will pass. Then you could refactor and optimize your implementation, your unit test should still pass.
Once you have a nice domain model and data access layer you could move to the web project where you create controllers, using the interfaces you previously defined (by making a constructor that takes this interface). You write a unit test for this controller by replacing the interface with a mock object, so that you can test the controller actions in isolation from your data access code.
And most importantly: don't be afraid to add classes and interfaces. I've seen people write huge methods that perform multiple things at the same time and which are difficult to test. Try isolating different tasks into methods that you could easily write specifications for: what output you expect for the different possible inputs.
For a long answer you should take small steps like this.
1)-First write a failing test
[Test]
public void AddSameTag()
{
UserMovie userMovie = new UserMovie();
userMovie.AddTag("action", "dts", "dts");
Assert.AreEqual(2, userMovie.Tags.Count);
}
2)- Write simplest code to pass the test.
public virtual void AddTag(params string[] tags)
{
foreach (var text in tags)
{
Tag tag =new Tag(text.Trim());
if (!movieTags.Contains(tag))
movieTags.Add(tag);
}
}
3)- Refactor
.
For ASP.NET MVC and TDD starter you can ignore Controller Test and focus on Domain by TDD.
You can look at ASP.NET MVC 1.0 Test Driven Development

How to write test case for mvc action filters?

I have an action filter which i got from the below link
http://blog.wekeroad.com/blog/aspnet-mvc-securing-your-controller-actions/
there is something called "RequiresAuthenticationAttribute"
for this i need to write test case.
how can i do this? form some of the blogs i read that we need to mock httcontext.
How can i mock this? what is the procedure that i need to do? is there any link for this?
Don't use the [RequiresAuthentication] attribute from Rob's blog. It's meant for a very old pre-release version of MVC. Use the in-box [Authorize] attribute instead.
Since the [Authorize] attribute is written by the MVC team, you don't need to unit test its logic. However, if you want, you can verify that it's applied to your controllers or actions. Simply get the Type or MethodInfo you're interested in, then call its GetCustomAttributes() method to get instances of AuthorizeAttribute. You can inspect those instances for the values that you expect.
If you want, you can look at the source code of AuthorizeAttribute for information on writing your own filter. Additionally, you can look at the official unit test of this type, so if you do end up writing a filter you can use a similar method to write your own type's unit tests.

How do I unit test an ActionFilter in ASP.NET MVC?

There is an ActionFilter on my controller-class. The OnActionExecuting method gets called, when an action of the controller is called in a web application.
Now I call the Action in a UnitTest:
NiceController niceController = new NiceController();
ActionResult result = niceController.WhateverAction();
Is there a way to have the ActionFilter called?
In order to have the ActionFilter called automatically, you are going to need to run the controller action invoker. This is possible, but it means that the MVC framework will try and execute the result. This means that you would have to use mocks to stub out the execution of the result. Again, that is possible, but it means that your unit test is becoming more mocks than actual code. It may be more correct to just test the filter directly. After all, the fact that OnActionExecuting is called is a feature of the framework, and you don't need to unit test the framework itself.
But I think that what you're really saying is that you want to test WhateverAction, and that action cannot work unless the ActionFilter has executed.
First, I would ask questions about this design. Is this correct? It might be. It is reasonable, for example, that an action with the Authorize attribute could presume that when it executes there is a logged in user. Of course, the action should test this, but the presumption is safe. On the other hand, actions should probably not require filters to do action-specific initialization. So you should ask the question, but the answer they well be that the design is correct.
In this case, the best decision for a unit test might be to manually execute the filter in the unit test, and to write a separate unit test which proves that the action is decorated with the correct attribute.
to write a separate unit test which proves that the action is decorated with the correct attribute
Here is how you can write such a unit test
Type t = typeof(MyController);
Assert.IsTrue(t.GetCustomAttributes(typeof(MyCustomAttribute)).Length > 0);

Resources