Hi,
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 = "[email protected]",
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.