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

5 thoughts on “Writing An Application Using TDD (Part 2) First List

  1. Sean Bennett

    Good to see you’re doing TDD. Why inject an IList, why not an IEnumerable? Why are the two assertions Assert.IsInstanceOfType(viewResult.ViewData.Model, typeof(IList)) and
    Assert.IsNotNull(result) necessary? What if the SUT changed the list? You check it is the same instance, but is it possible the elements were changed by the Sut? Nice glimpse of testing ASP .Net MVC. Thanks. Sean. @theHumanFlag on Twitter.

    Reply
    1. Angel "Java" Lopez

      Hi people!

      @MartinSalias: I will apply your suggestions; in the next posts, the example will be refactored to your names.

      @theHumanFlag: You are right, I could use IEnumerable. But I’m doing a little up front design. I could switch to IEnumerable, for the next posts.
      I’m using IsNull to have a better message, in case of error, to clearly distinguish between the case “data is null” from “data is not the expected type”.
      The SUT can change the elements, in the future. But my current expectations are: it doesn’t change them.

      Keep Tuned!

      Reply
  2. Pingback: Writing an Application using TDD (Part 3) First Detail « Angel “Java” Lopez on Blog

  3. Pingback: Escribiendo una Aplicación usando TDD (Parte 3) Primer Detalle - Angel "Java" Lopez

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s