TDD'ing MVC Controllers to drive design - asp.net-mvc

I am starting out on a new project (well, restarting an existing one), and trying to adopt TDD (for the nth time) for all the benefits that it should bring.
I believe that TDD will result in my tests driving me to write only the code that I need to write, but it will drive me to write the code that I NEED and not leave some out.
This is where my current state of uncertainty comes in.
Consider the story:
"A user must be able to add a widget, doing so they are taken to view the details of the newly added widget."
OK, so working from the UI (as that's where a user will add their widget from, and not using Visual Studio and a set of assemblies that I write)... I begin with the following test, writing the very minimal so that the test passes.
So I started out with the controller throwing a NotImplementedException, then returning a View()... the following was the first point that I had written the fewest lines I could to make the test pass.
[TestFixture]
public class WidgetControllerTester
{
[Test]
public void Create_IfBusinessModelIsValid_ReturnRedirectToRouteResultToDetailsAction()
{
// Arrange
var currentUser = new User
{
DisplayName = "Fred",
Email = "fred#widgets.com",
Password = "pass",
Status = UserStatus.Active
};
var model = new WidgetModel();
var controller = new WidgetController();
// Act
var actionResult = controller.Create(currentUser, model);
// Assert
actionResult.AssertActionRedirect().ToAction("Details");
}
}
public class WidgetModel
{
}
public class WidgetController: Controller
{
public ActionResult Create()
{
return View("Create");
}
[HttpPost]
public ActionResult Create(User currentUser, Widget model)
{
return RedirectToAction("Details");
}
}
Now I realise that additional tests for invalid models and checking of model state will evolve from additional stories.
However I can't see a clear path of how I would leverage additional tests to drive further code within the controller.
For instance, I know at some point I will want to make a WidgetService call from the Create action. Am I missing something obvious (not being able to see the wood for the trees kind of stuff) how I can progress the controller code with additional tests?
Talking about the WidgetService, I expect that I will write a WidgetServiceTester and for th e time being references within the controller will most likely be mocked.
Some thoughts I have had...
Create a new test called Create_IfModelIsValid_WidgetIsAddedToRepository, but how does this clearly lead onto service calls in the controller action?
I need to write a more detailed story stating that the model needs to be inserted into the repository/database, etc?
Am I muddling up elements of TDD and XP?
Thanks for reading, I would appreciate any feedback and insights to the best practice for progressing.
Joe.
EDIT 27 Feb 2010
I found the following article Iteration #6 – Use Test-Driven Development (on asp.net) (http://www.asp.net/%28S%28ywiyuluxr3qb2dfva1z5lgeg%29%29/learn/mvc/tutorial-31-cs.aspx) which demonstrates the sort of thing I was after, however they seem to consider addition of repository/service to the controller as re-factoring... I personally don't agree, am I wrong? :)
I'm going to think about writing a test that checks the ViewData of the Details action and update this question once I have.

Joe. I feel a lot of the same uncertainty, sometimes. But I also think that most of what you're missing is those up-front stories. First, you should decompose your story just a tad to create the actual developer requirements. Here's what I mean:
"A user must be able to add a widget, doing so they are taken to view the details of the newly added widget."
Ok, so to me, that breaks out questions as follows, which can help you think of tests:
"A user" -- where did the user come from? How are they logged in? (if you're using the default AccountController and tests, then this is already there, if not, you'll want tests for getting the login form, logging in, validating both successful and failed logins, etc)
"add a widget" -- to what (I don't mean implementation, I just am pointing out that this implies that you're either going to hit a repository or a service, unless 'add' just means add it to the running instance and you don't need persistence)? does the widget have to be valid at this point, or can invalid widdgets be saved and made valid later? This implies to me tests that a repository or service has a method hit (save(), insert(), add(), whatever (not the internals of the method, until you get to testing your service/repo, just that the controller does its job by calling it), check what happens on a valid/invalid widget (you need to expand your story a bit or add a story to cover what should happen on valid/invalid widgets)
"doing so they are taken to view the newly added widget's details" -- reworded slightly, but basically what you said. Always? or only on success? Is this view editable or read-only (i.e. Edit action or Details action)? Is there a message to the user that tells them that they've been successful, or should they infer from the fact that they're viewing their widget that they were successful? This should drive tests that do things like check properties on the returned actionresult and check the values stored in TempData (status message) as well as checking what happens in both paths (success or failure).
that's just a quick shot, but basically that's the thought process. you can also do the same w/ other stories, and for that matter generate new stories to cover more application behavior.
A couple thoughts on your design going forward.
Your next test should look at what I wrote above first, which is the fact that the controller's create POST action should 1) receive needed data (your params), 2) call that service/repository to "add" the widget, 3) possibly do something if that add fails (this is in your design; I've gotten to where my controllers assume all will go well and I handle failures through attributes, but thats' a personal design decision), 4) redirect to details.
So, your next test would be using a mock (I prefer the moq library on google code, but whatever you have will work). You'll need some interface to describe the service your controller will call, and you pass in a mocked implementation of that to your controller under test in order to ensure that it's calling the correct method. In Moq, that'd look something like this:
[Test]
public void Create_CallsRepository()
{
// Arrange
var currentUser = new User
{
DisplayName = "Fred",
Email = "fred#widgets.com",
Password = "pass",
Status = UserStatus.Active
};
var model = new WidgetModel();
var mockService = new Mock<IService<WidgetModel>();
mockService.Setup(s=>s.Add(model)); //.Returns(whatever) if it returns something
var controller = new WidgetController(mockService.Object);
// Act
var actionResult = controller.Create(currentUser, model);
// Assert
mockService.Verify(s=>s.Add(model));
}
That makes some design assumptions, of course, but the tension of how to write your tests vs how your objects should be called / handle things is part of what makes TDD so valuable.

Related

Alternative to StackTrace.GetFrame... to finding the action on a controller that called a method

Setup:
I have written an ASP.NET MVC wizard, based originally on Steve Sanderson's wizard (Pro ASP.NET MVC 2 Framework). My wizard is generic and is a dream.
Each Wizard step is an action.
However, I have now released an app that uses the wizard extensively. Obviously, the app is in release mode.
The WizardController<> class is the base class to all my wizards. It has an OnActionExecuting method that I suspect can provide the solution to my problem. The question is how, or rather, to traverse the stack in the right order, what the problem is...
The Problem:
The code, deep in the WizardController, uses:
var stackTrace = new StackTrace();
string actionName = stackTrace.GetFrame(n).GetMethod().Name
to get the name of the action that has called this code (where n is the frame I know is the calling action... in debug mode that is). This allows me to establish which wizard step / action I am on.
This works fine in debug mode, but in release mode, the compiler optimises my code. So n may, or may not, represent the correct frame in my stack.
The reality is that, in release mode, sometimes n does not represent the correct frame. And sometimes is not good enough. Sometimes is my problem. I want a bullet proof solution.
Question:
So what alternative to using stacktrace?? I suspect I can use my OnActionExecuting method to grab the name of the action, which is what I need, as this name is what identifies the step in my wizard.
But how?
Forget to be or not to be. How? That is the question.
OK, writing the post made me realise that the answer was staring at me blue in the face.
The ActionExecutingContext parameter of the OnActionExecuting method gives me the handle I need on the Action name, as follows:
In my WizardController class I add the following:
private string ActionName { get; set; }
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
ActionName = filterContext.ActionDescriptor.ActionName;
// All the other stuff...
}
I can now use the ActionName property instead of:
stackTrace.GetFrame(n).GetMethod().Name
where n might be known in debug mode, but is very definitely not known for sure in release mode.
Phew!
Hope this helps someone else who, like Narcissus, has fallen into the reflection trap.

Controller Tests for Service Layer Logic

I have a solution with the following architecture MVC app > Services > Repositories. Now lets say I have a Document Model and a Document has many Notes. I have a Notes controller with an AddNote(documentID) action. Now my business rules say that only the users associated with the document can add notes so I enforce this. I am currently going with the following method:
public ActionResult AddNote(int documentID)
{
try
{
NoteCreateEditViewModel viewModel = Mapper.Map<Note, NoteCreateEditViewModel>(noteService.GetNewNote(User.Identity, documentID));
return View(viewModel);
}
catch (BusinessLogicException validationException)
{
// Send user somewhere else.
}
}
noteService.GetNewNote(User.Identity, documentID) throws a BusinessLogicException should the user have no right on the Document. I am using an exception as this seems to be the best way to handle business/validation violations (although I personally feel this is bad use of exceptions!).
When testing the above from a controller test, should I just be testing that the correct redirect (or whatever) happens should the BusinessLogicException be thrown or should I be simulating an unauthorised user/non existent documentID etc? In my mind, the service test for GetNewNote(User.Identity, documentID) would be the place to simulate an unauthorised user as this ensures my tests are testing the core functionality of a particular piece of code.
However, if I dont write a controller test which simulates an unauthorised user generating an Exception, then how will someone who looks at my tests in the future understand that the desired functionality of AddNote is to prevent unauthorised users from adding notes. If they dont understand this they may be tempted to simply initialise a new Note directly in the controller, rather than through noteService.GetNewNote(User.Identity, documentID).
So should I be testing more in my controllers or is there a much simpler design in adding associated models?
In your unit test you should mock the noteService.GetNewNote method call so that it throws a BusinessLogicException. Then assert that the controller action returned a redirect result.

Which amongst the following is a better way to write Unit Test and go ahead with TDD in ASP.NET MVC

After reading about MVC and Test Driven Development for quite a bit, I am just getting started on converting my webforms app to MVC. I am using this book as one of the references to learn TDD in ASP.NET MVC.
A Unit Test from that book is as below:
[TestMethod()]
public void Register_Can_Get_To_View()
{
var target = new AccountController();
var results = target.Register();
Assert.IsNotNull(results);
Assert.IsInstanceOfType(results, typeof(ViewResult));
Assert.AreEqual("Register", target.ViewData["Title"]);
}
I am also having a look at the nerddinner source code from codeplex and there a similar Unit Test is written as follows
[TestMethod]
public void Index()
{
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
In the first case, the author is comparing the type of results with ViewResult. However in the second case, the result is being casted as a ViewResult and that is not being tested.
Which is better and do I need to really test in detail as shown in the first case?
Ideally you test the result for all the things it could get wrong, where being null might only be the first.
You should assert all of the values of the result, and in fact would test them from different angles (i.e. with different inputs) so that you're testing that those results change correctly relevant to the input. (i.e. to prove you've not hard-coded the values required by one single test just to get it to pass).
The idea being:
Write a test that doesn't compile.
Write just enough to get it to compile, but still fail (i.e. NotImplementedException).
Write just enough to get the test to pass (you can hard-code the unit under test to get the test to pass).
Write another test that fails (which forces you to put a better implementation in than the hard-coding to account for the different input).
Make the changes so the test passes again.
Repeat until the unit is fully tested (i.e. all possible/suitable inputs are accounted for, and unsuitable ones are checked and refused appropriately).
Sometimes you can short-circuit step 3 and write what Kent Beck refers to as the Obvious Implementation for things that you know from experience are going to be very simple. You wouldn't do this for complex units, but for a method that reverses a string or adds two numbers together you can go ahead and just write the implementation properly.
In this case, I'd consider asserting the following:
That the controller action result was not null.
That the Model property was of the correct type (assuming strongly-typed views).
That each property on the Model or each value in the ViewData was the correct value for the given input.
The first test looks as if the controller action is using ViewData instead of view models. For me this is bad. It uses magic strings and it is extremely brittle. So no longer need to comment on it.
The second test doesn't do anything useful other than verifying that the controller action returned a view.
But a more real world controller action will pass a view model to this view. So you need to test this. Personally I prefer MVCContrib TestHelper as it makes my unit tests very fluent and readable:
[TestMethod]
public void Index()
{
// Arrange
var controller = new HomeController();
// Act
var actual = controller.Index();
// Assert
actual
.AssertViewRendered()
.WithViewData<MyViewModel>()
.ShouldNotBeNull("the view model was null");
}
Here we assert that the controller action rendered a view and that the view model which was passed to it wasn't null and it was of the expected type because the corresponding view will be strongly typed to this view model.

How do I create a concise and RESTful wizard under MVC?

I try to be as RESTful as possible in building applications but one thing that I'm never sure about is how to create a wizard-type work flow, be RESTful and concise.
Take, for example, a multi-page sign-up process.
Option 1: I can create a controller for each step and call new or edit when user gets to that step (or back to it). I end with step1_controller, step2_controller, etc...
Option 2: I can create a one controller and track where they are in the sign-up process with a param, session variable, state-machine - whatever. So I'd have signup_controller/step?id=1
The first option is strictly REST, but not very concise and ends with some number of extra controllers. The second options is more concise, but breaks REST, which I'm willing to do, but I don't take it lightly.
Is there a better option?
I'm working in ruby on rails, but this question applies to other MVC implementations, like ASP.NET MVC
If you apply some DDD logic here, which compliments the "M" in MVC, the state of the UI (registration progress) belongs in the Application Layer, which can talk directly with the Domain and Infrastructure layers (Four layers: UI, Application, Domain, and Infrastructure). The concept of DDD makes you "think" about how to solve the solution in code first. Let's step through this...
It's the Progress Bar
The state you want to maintain here is the step or progress of the registration. So, my first step would be to document progress or "steps". Such as, Step 1: Get Username/Pass, Step 2: Get Email. In this case, I would apply logic to "move" the Model to the next step. Most likely with a NextStep() method on the a RegistrationService (RegistrationService.NextStep()).
Ah, but it belongs in the App layer
I would create a service in the Application layer called RegistrationService. I would place a method on here called NextStep(). But remember, the Domain would not hold the state of the model here. In this case, you'd want to focus the state at the Application layer. So in this case, NextStep() would act upon not a model object (since it is not part of the Domain responsibility), but instead the UI. So, you need something to retain the state of the Registration process.
Get away from the Domain Model, how about a ViewModel?
So now we know we have to retain the state of something in the UI. MVC allows for a concept called ViewModels (in ASP.NET MVC, not sure what RoR calls it). A ViewModel represents the model that will be displayed by the view, and/or partial views.
The ViewModel would be an excellent place to save the state of this object. Let's call it, RegistrationProgressViewModel() and stick a NextStep() method on it. This, of course, means that the Application layer would have to retain the location of the RegistrationProgressViewModel, and the APplication layer would change the internals of it based on NextStep actions. if it is complex, you may want to create a RegistrationProgressService() in the application layer and place the NextStep() within it to abstract your logic away.
How to pass the ViewModel around?
The final piece is how to track the state of that object. Since web applications are stateless, you have to retain control by some other means then the application. In this case, I would revert to either: 1) Serializing the ViewModel to the client and letting the client pass it back and forth, or 2) Keep a server-side copy of the ViewModel, and pass some type of identifier back and forth to the client and back.
This is a good example to think about, as I have not performed this myself yet. For #2, the most secure and insured way of saving the state of this ViewModel is to persist it to the via the Infrastructure layer (yes, the APp layer can talk directly to the Infrastructure layer). That seems a lot of work to me, for something that may die off and I would have partial registrations sitting in my DB.
But, #2 would keep the user's private info (username, password, email, CC #, etc) all on the server side and not pass it back and forth.
Finally, an answer!
So, after walking through it, we came up with:
Create a RegistrationProgressViewModel() in the Application layer.
Create a RegistrationProgressService(), with a NextStep(ViewModel vm) method, in the Application layer.
When NextStep() is executed, persist the ViewModel to the database through the Infrastructure layer.
This way, you never have to track what "step?id=2" on the View or UI itself, as the ViewModel gets updated and updated (Authenticated, Verified, persisted to DB) as you move forward.
So, your next concern would be to "move forward" in the UI. This is easily done with 1 controller, using step or named steps.
I apologize, but I am writing C# code below as that is my language.
public class RegistrationController : Controller
{
// http://domain.com/register
public ActionResult Index()
{
return View(new RegistrationProgressViewModel);
}
// http://domain.com/register
// And this posts back to itself. Note the setting
// of "CurrentStep" property on the model below.
//
public ActionResult Index(
RegistrationProgressViewModel model)
{
// The logic in NextStep() here checks the
// business rules around the ViewModel, verifies its
// authenticity, if valid it increases the
// ViewModel's "CurrentStep", and finally persists
// the viewmodel to the DB through the Infrastructure
// layer.
//
RegistrationProgressService.NextStep(model);
switch (model.CurrentStep)
{
case 2:
// wire up the View for Step2 here.
...
return View(model);
case 3:
// wire up the View for Step3 here.
...
return View(model);
case 4:
// wire up the View for Step4 here.
...
return View(model);
default:
// return to first page
...
return View(model);
}
}
}
You'll notice that this abstracts the "Business Logic" of verifying the model's internal state into the RegistrationProcessService.NextStep() method.
Good exercise. :)
In the end, your "RESTful" url is a nice and clean POST to: /register, which expects a ViewModel with specific properties filled out. If the ViewModel is not valid, /register does not advance to the next step.
I'm actually less concerned about maintaining REST in a one-shot wizard. REST is most important, I think, with repeatable actions -- you want the url to be basically bookmarkable so that you get back the same view of the data regardless of when you go there. In a multi-step wizard you have dependencies that are going to break this perspective of REST anyway. My feeling is to have a single controller with potentially separate actions or using query parameters to indicate what step you are on. This is how I've structured my activation wizards (which require multiple steps) anyway.
Although the answers are very nice options indeed I still use the approach given in:
Shoulders of Giants | A RESTful Wizard Using ASP.Net MVC.
It is definitely worth a look. Though I must say, the answers given here make me think to remake this wizard when I have the time.

ASP.NET MVC - User Input and Service/Repository - Where to do Validation?

This might be too opinionated a question, but looking for help!
I have been trying to refine my ASP.NET MVC program structure. I just started using it at preview 5 and it is my first foray into business application development -- so everyting is new!
At the controller level, I have a service object responsible for talking to the repository and taking care of all business logic. At the action level, I have an object that holds all view data -- user input and generated output -- that I'll call view object (is there a general term for this?). Unlike most examples I see, this object is not a database object, but an object specific to the view.
So now I want to add user validation. The problem is, I'm not sure where to put it. It makes the most sense to me to do it in the Service layer. The Service layer is responsible for all the business logic and validation is business logic. On the other hand, most validation frameworks that I see are for validating an object, which makes me think the view object should be validation aware. Finally, there are some validation methods that would require a database connection (checking if a user input field has a corresponding database record for example), and the view object has no concept of a database, only the Service.
So some options I see are:
Do validation in the Service.Method on the parameters passed to the method.
Do validation in the view object before calling Service.Method.
Do validation in the view object but make the Service.Method require a view object reference so it is initiating the validation on the object.
I'm sure there are more. I'm curious of how other people handle user input validation in the MVC sense. I've previously used the Enterprise Validation Block and liked being able to use stock validators for everything, but I'm not sure how to make it fit into a seperate view object and service layer. It would be easy if they (view object / service) were the same object, which is maybe what people do? Like I said, its all new to me and I'm looking for best practice / patterns.
I typically do basic validation (required fields, email format, etc.) in the controller action when the form is submitted. I then let the business layer handle validation that requires business knowledge. I usually double check the basic stuff in the business layer as well, so if I expose that logic through web services or use it in another application later, I still have validation where it is most important (IMO).
There are some interesting links on this
MVC & MS Validation Application Block
MVC & Data Annotation Validators
Form Validation video
Personally, i've added validation to my Service layer objects (first two links). This way, if any method in any controller decides to call my service method .. the logic is all checked and boxed in one location. DRY.
That said, i also have some UI validation (3rd link) .. to reduce the roundtrip time.
Lastly, the current MVC dll's have the ability to pass error messages back to the UI .. so the view can display them nicely. Check out :-
ViewData.ModelState.AddModelError(key, message)
hth!
Check the following blog posts
http://blog.codeville.net/2008/09/08/thoughts-on-validation-in-aspnet-mvc-applications/
http://www.emadibrahim.com/2008/09/08/client-server-side-validation-in-aspnet-mvc/
Take a look at the S#arp Architecture project. Validation is handled on the model to ensure that no entity is persisted to the database in an invalid state. It does this by using NHibernate.Validator and attaching it to NHibernate's save and update events.
Personally, this approach makes the most sense to me since you don't have to duplicate your validation logic in multiple controllers.
I was afraid I'd get no replies for my post, happy to be wrong!
I've read those links before, but probably a month or more ago, and re-reading them with what I understand now has been very helpful. I really like Steve Sanderson's post with the sliding scale, but wish he would show an example of validating something at the right-end of the spectrum.
As an example in his blog he gives: " 'usernames must be unique' will probably be enforced in your database". So would this be something like:
public static void SavePerson(Person person)
{
// make sure it meets some format requirement
// in this case the object is responsible for validation and the service layer is the caller
person.EnsureValid();
// todo: action to verify username is unique by checking database
// in this case the service layer is responsible for calling and implementing validation
// todo: action to save to database
}
This makes sense, and would show my trouble grasping where to put validation as it is inside both the service layer (very unique name) and view-object (verify formats).
Another concern I have is the service layer starts to balloon with validation logic. Maybe split it out to a different class or something? In my case some validation logic might be shared between services, so I would like to think of a DRY way to implement this. Fun stuff to think about!
Emad Ibrahim's link is great in that once I start to understand this process a bit more I was going to look for a way to generate javascript client-side validation using the same set of rules without having to repeat code. He already has that :)
I have heard about S#arp but not sat down and seen how it works (I'm not sure if there is much in the way of demos on it, or if downloading the code is the demo!). I'm not sure if doing validation on the database model only would be sufficient. It seems to me there would be plenty of valid model states with regards to the database that business logic would say are invalid (such as date ranges / must be before / after / etc). Those are the cases that are wracking my brain :)
Also, a link I liked (googled it after I saw Emad reply to Steves post with BLL and no idea what it meant... duh):
http://en.wikipedia.org/wiki/Business_logic_layer
So I didn't know it, but I think this is the model I'm writing to: Business Process object that handles data interactions, and Business Entities that are logical models rather than database models. I think I need to start reading some more fundamental patterns and practices with this stuff to better understand the concepts (it seems like a lot of this is stuff Java people write vs. .NET people). It might be time to take a step back :)
I have come across this same issue in a recent project. First, to restate the problem, I am trying to follow the domain-centric approach of DDD. I have entities composed into aggregates that can validate themselves, and the repositories verify validity on save. The UI can also get validity information from an aggregate in order to display error feedback to the client. The general approach is to leverage as much as possible ASP.NET MVC's model binding, and validation/form UI helpers. This creates the simple UI flow: 1) bind, 2) validate, 3) if valid, save, else re-populate view.
However, it is not directly obvious how to do leverage ASP.NET MVC and this simple flow when DDD services are involved. Originally, I developed my services as such:
public class SomeProcessService
{
public Result Execute(int anAggregateID, int anotherAggregateID, string someData)
{
// validate input
// if invalid, return failures
// else
// modify aggregates
// using (transaction)
// {
// save aggregates
// commit
// }
// return success
}
}
The problem is that the validation and the save are inextricably linked in the method. To leverage the MVC model binding, we need something that serves as a model to bind to. I am refactoring to this:
public class SomeProcessService
{
public class Request : IValidateable
{
public int AggregateID {get;set;}
public int AnotherAggregateID {get;set;}
public string SomeData {get;set;}
public Result Validate()
{
// validation
}
}
public void Execute(Request request)
{
// validate input by calling request.Validate()
// if invalid, throw new ValidationException(request)
// else
// modify aggregates
// using (transaction)
// {
// save aggregates
// commit
// }
// return success
}
}
This repurposes the Parameter Object pattern to separate method input validation. I can bind to a SomeProcessService.Request object in my controller, as well as get validation information there. If all is well, from my controller I initiate the service call using the Request object as the parameter. This approach seems to happily marry DDD services with ASP.NET MVC validation requirements.

Resources