Angel \”Java\” Lopez on Blog

March 22, 2011

Writing An Application Using TDD (Part 2) First List

Next post in this series
Previous post in this series

Thanks to a suggestion by @MartinSalias, I choose to develop a simple domain: my personal library, my books. In this first code iteration, I want to list the book genres: Physics, Mathematics, Biology, Literature… (similar to genres in MvcMusicStore by @jongalloway).

First, I created the ASP.NET MVC Solution (I’m using Visual Studio 2008) (the code for this post is in my AjCodeKatas Google Project, under trunk/AppTdd/Step01)

Then, I add a test project:

I added references to System.Web.Mvc and MyLibrary.Web, to be used in this test project.

I added a new test:

I cleaned the code of my first test class, removing unneeded methods. The result:

namespace MyLibrary.Web.Tests.Controllers
{
    using System;
    using System.Text;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    [TestClass]
    public class GenreControllerTests
    {
    }
}

Then, I added my first test:

        [TestMethod]
        public void GetGenres()
        {
            IList<Genre> genres = new List<Genre>()
            {
                new Genre() { Name = "Mathematics" },
                new Genre() { Name = "Physics" },
                new Genre() { Name = "Biology" },
                new Genre() { Name = "Literature" }
            };
            GenreController controller = new GenreController(genres);
            ActionResult result = controller.Index();
            Assert.IsNotNull(result);
            Assert.IsInstanceOfType(result, typeof(ViewResult));
            ViewResult viewResult = (ViewResult)result;
            Assert.IsInstanceOfType(viewResult.ViewData.Model, typeof(IList<Genre>));
            Assert.AreSame(genres, viewResult.ViewData.Model);
        }
		

The idea: create the controller, feed it with a list of genres, then invoke the Index action, and test the returned action result. The code didn’t compile: the controller didn’t exist, there were no Genre class. So, I wrote the Genre class in Model folder at MyLibrary.Web:

    public class Genre
    {
        public string Name { get; set; }
    }

A simple GenreController (added with right click on Model folder):

The wizard created this code:

    public class GenreController : Controller
    {
        //
        // GET: /Genre/
        public ActionResult Index()
        {
            return View();
        }
    }

I modified it to have an appropriate constructor:

    public class GenreController : Controller
    {
        public GenreController()
        {
        }
        public GenreController(IList<Genre> genres)
        {
        }
        public ActionResult Index()
        {
            return View();
        }
    }
	

Note that my intention was to compile the test: the list of genres are not used by the controller, yet. With all these changes, I could compile the solution, and run the test:

The result was:

The problem:

As expected. This is part of the TDD cycle: compile, red, and now, go for green.

I changed the controller behavior (the interface was already completed):

    public class GenreController : Controller
    {
        private IList<Genre> genres;
        public GenreController()
        {
        }
        public GenreController(IList<Genre> genres)
        {
            this.genres = genres;
        }
        public ActionResult Index()
        {
            return View(genres);
        }
    }

Now, the test result:

Triumph of mind over matter! ;-)

Now, time for refactoring. Well, I have not much for this now. I could improve same naming. The main missing piece: a view. Note: the controller is not prepared, yet, for production. It has no genre provider object.

Next steps: improve controller to use a view, add CRUD actions with tests, and views.

You could ask: where is the repository of genres? where is the database? what about a service layer? domain separation? Ok, all valid questions. My idea is to show, with incremental steps, how all those artifacts arise from improving the controllers, actions, by the force of new tests and refactoring. As I wrote in my previous post, this is a kind of top-down approach. In this case, the domain is simple, so I can start from the top presentation layer. After this simple example, I will switch to a less simple domain. In this case, we can start testing the domain, before any presentation layer.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Theme: Shocking Blue Green. Get a free blog at WordPress.com

Follow

Get every new post delivered to your Inbox.

Join 67 other followers