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.GetNewNotemethod call so that it throws aBusinessLogicException. Then assert that the controller action returned a redirect result.