3.4. Implementing the Pizza Store

The following section will describe how to develop and write unit tests for the ASP.NET MVC application called the Wrox Pizza Store. The concept for the store is simple: a user should be able to navigate to the store, select items from a menu, pay for their purchases, and then expect delivery of their ordered products.

3.4.1. Downloading and Installing ASP.NET MVC

ASP.NET MVC is a free download available from http://www.asp.net/mvc/. The installation is a MSI package that contains a collection of assemblies relating to the core framework itself, JavaScript files including JQuery and Microsoft Ajax, and a set of Visual Studio templates to help you create ASP.NET MVC applications.

3.4.2. Structuring Your ASP.NET MVC Applications

The initial structure of your application is important in terms of how maintainable the system will be at the end. If you start off with a good structure it provides a firm foundation for you to build upon.

After downloading and installing ASP.NET MVC, you will have a set of Web Templates within Visual Studio in the same way you had templates for ASP.NET WebForms. By using these templates you can create an ASP.NET application by simply entering a name, in this example HelloWorldMVC; the template will create the structure, and add correct references and initial code to help you get started. After creating and executing the application, it should look similar to Figure 3-2.

Figure 3-2. The website generated by the MVC template

The solution within Visual Studio created by the template is broken into different sections to indicate the roles and responsibilities as shown in Figure 3-3.

Figure 3-3. Default MVC solution structure

First you'll have two directories for resources: content and scripts. Content is designed to store style sheets, images, and other static resources for the site. The scripts folder contains JQuery and the Microsoft Ajax framework. ASP.NET MVC is the first Microsoft product to ship an open source library in the form of JQuery, which is very exciting news for the open source community and for developers who work on the Microsoft platforms. Both of these frameworks support you when adding JavaScript to your site.

The Models folder is empty, but the Controllers folder currently has two classes: AccountController and HomeController. The AccountController is responsible for the authentication for the system. The HomeController is responsible for handling the logic for the Index and the About pages.

Within the Views folder there are multiple sections. The Accounts folder has the authentication pages. The Home folder contains the About and Index pages. With MVC, unlike WebForms, ASP.NET no longer requires code-behind files as all the logic is within the controller; as a result you simply need the ASPX file. One important item to notice is that the controller's name and the name of the Views folder match. This convention allows the framework to identify which View pages to render based on the controller and action method. The Shared folder contains all the pages or user controls that are shared among the different views in the system; for example, the master page for the site.

The project will be compiled into an assembly called HelloWorldMVC. When creating the project you also have the option to create a test project to store your unit tests. By default, this is the project name with .tests appended, such as HelloWorldMVC.Tests. As described in Chapter 2, the naming of the project, folder, and classes should reflect the names within your main application making it easier to navigate and understand how the tests relate to your implementation. By default, MVC selects an MSTest based project; however, if you've installed the correct extensions you can select from xUnit, MbUnit, NUnit or any other framework.

Although this is the default solution provided by Microsoft, we feel a different structure is more logical. Our main bug-bear with the default structure is how it mixes the business logic and view logic in the same assembly and project structure. We feel better to maintain a clear definition between the two because it helps you think more logically about what belongs where. All the code, actual C# code, should live in a separate assembly to the View templates — the ASPX files.

The folder structure we're recommending for you is shown in Figure 3-4 (found in 3-TDDChapter 3 SamplesWroxPizzaStorev1WroxPizzaStore) and is a basic structure for setting up solutions.

All the assemblies are prefixed with the name of the application, in this case WroxPizza. This will help identify assemblies against possible third-party assemblies within the output directory.

In the solution there are four different projects: .Core, .Tests.Unit, .Tests.Integration, and .Web. WroxPizza.Core is a class library that will store all your application logic. There are also three main root folders: Data, for your data access logic (which will be covered later); Model, to store your domain logic; and Web, which stores your controllers, bootstrapping code for the website, and any shared UI logic.

WroxPizza.Web stores all your mark up and content for the web application. This should contain no C# code, with the exception of Global.asax.cs and Default.aspx.cs, which are required due to the core ASP.NET engine. The result of having your application structured this way is that you know everything within .Core needs to be unitintegration tested while everything in .Web should be left to UI automation.

Figure 3-4. Author-recommended MVC folder structure

The final two assemblies are your test assemblies. The assemblies are split into two for an important reason. Your Tests.Unit assembly will contain most of your tests, taking advantage of mock and stub objects where required to break the dependencies. Because this assembly will contain most of your business logic, you want it to be fast to run and to be confident that all the tests will pass every time. If a test fails in this assembly then you must have broken something. Your Tests.Integration assembly on the other hand will be testing against a real implementation; for example, a real database. This assembly will be slower to execute and more error-prone. However, because it's only focusing on your integration tests then it shouldn't need to be executed as often. If you had automated UI tests, these would be stored under WroxPizza.Tests.UI.

With the basic structure in place you can start building your application. As with most applications, the hardest part is figuring out where to start. There are three possible starting points: you can start at the UI and work down to the DB; you can start at the DB and work upward toward the UI; or you can start in the middle and fan out working on UI and DB as required. When using TDD and mock objects, beginning at the middle layer and then fanning out tends to be the easiest. This drives the business value and core functionality more effectively.

As you learn more about your requirements and start interacting with the UI and DB, this layer will be subject to changes. However with tests in place and a decoupled system, this shouldn't be too painful.

3.4.3. Feature 1: Displaying Products from Database

The first feature to develop is one of the core features for the application: displaying products on a web page. Although this sounds like a simple task, it provides a core set of interactions with your system and will allow you to define an initial design and architecture for a core part early on. This will allow you to follow a similar approach when building the rest of the application.

As such, it also provides a great example for explaining the concepts and how to start building features using TDD.

The initial set of samples can be found in 3-TDDChapter 3 SamplesWroxPizzaStore. The final application can be found at SampleWroxPizzaStore.

3.4.3.1. Creating the Controller

As previously mentioned, we will be following the fan out approach to software development and with the MVC pattern; the core part is the controller. To start with, you'll be displaying the products to form a menu for your pizza store. The initial name could be ProductsMenu, because it is responsible for displaying the menu. This controller will be responsible for first obtaining the products from the database and then passing them back to the UI to display on the correct page.

When using TDD, your first approach when writing code is to always to create a new test. Your controllers are going to be isolated from all external dependencies as they are going to be unit tested with testability taken into consideration from the beginning. By coding the test upfront, those considerations are easier to implement and get right instead of having to try and retro-fit the problem.

To start, you first create a new class under WroxPizza.Tests.Unit.Web.Controllers called ProductsMenuControllerTests. With the class in place, you can start writing test methods. The first test will verify that the controller is accessing the database correctly and pulling back all the products available. This test is called Index_Returns_All_Products_In_Database.

An initial attempt at the test would be similar to the next code example. The aim of the test is to describe how you are expecting to interact with the controller and method. In this example, the test constructs a controller called ProductsMenu and calls the Index() method:

[TestFixture]
public class ProductsMenuControllerTests
{
        [Test]
        public void Index_Returns_All_Products_In_Database()
        {
            //Incomplete
            ProductsMenuController controller = new ProductsMenuController();
            controller.Index();
        }
}

This test has two major problems. First, there is no expected data so you don't know what data will be returned. Secondly, the test is not self-verifying and as such it will always pass.

With the first problem, although you know you need to store the products you want to display, you may not know exactly how or where at the moment. A database seems the most logical, but as you move forward you might need to access a web service or an XML data file to obtain the information. Because of this, you should abstract away from this low-level dependency, such as a database, and have your controller talk to a high layer interface. At this point, you should be remembering similar concepts discussed in Chapter 2. By communicating to the abstract implementation, you have the flexibility to replace the implementation during testing allowing you more control.

You know you need to access the data from an external source. For now, you will use Rhino Mocks to create a stub object for an IProductRepository. A class implementing IProductRepository will be responsible for returning all the products within the store. The Repository pattern is a well-known data access pattern, which was defined in Martin Fowler's Patterns of Enterprise Application Architecture book, published by Addison-Wesley (2002), and is designed to mediate between domain objects data mapping layers. Your domain objects will be objects such as Product and Order while your data mapping will handle the translation between domain objects and the underlying data store, such as a table.

Although the pattern doesn't define which method a Repository object should have, the .NET community has defined an approach they take and a defacto standard has emerged that people generally follow. The standard set of methods providing core functionality include Get, GetAll, FindAll, FindOne, SaveOrUpdate, and Delete. This standard set of methods generally exists on an IRepository interface with custom methods being defined on the more targeted interface. This keeps the IRepository interface lightweight and focused allowing other interfaces to also remain lightweight while being targeted and providing functionality. This relates to the Interface Segregation Principle as discussed in Chapter 2.

In order to implement this test and have our controller communicate with some data source you will need to stub (as described in Chapter 2) the IProductRepository. This inherits from IRepository; however, it will be the more targeted interface based on how to return product related information:

IProductRepository repository = MockRepository.GenerateStub<IProductRepository>();

By stubbing this interface, you can define the result you want to be returned when a part of our system calls the particular method. This is how our test can be in control of the data being passed around the object being tested:

repository.Stub(r => r.GetAll()).Return(products);

In this case, when the GetAll method is called on our Repository object, you want the products' collection defined next to be returned. This collection simply contains a single product; however, it is enough data to allow us to prove if the system is working as expected:

List<Product> products = new List<Product>
                             {
                                new Product
                                {
                                   ID = 1,
                                   Name = "Classic Cheese",
                                   Description = "Classic Cheese",
                                   BasePrice = 8.00
                                },
                             };

You have now defined a test and an interface that will return the data. The next stage is to inject the stub object into the controller so the controller can access the functionality provided via an object implementing IProductRepository. Remember, the controller isn't concerned with the actual details, it just needs an object to provide the functionality requested. The easiest way to handle this is using constructor injection where the external dependency is provided as an argument on the constructor of the object requiring the functionality (as covered by The Dependency Inversion Principle in Chapter 2) as shown next:

ProductsMenuController controller = new ProductsMenuController(repository);

The controller now has the ability to obtain data. However, the test still doesn't have any way of knowing what data was returned from the controller.

With ASP.NET MVC, any action that should render a view needs to return an object of type ActionResult. The ActionResult is an abstract class with a number of different subclasses within the framework. Each subclass has a number of different options and additional information that controls how the framework processes responses and redirects.

In this example, your Index method will return a ViewResult, indicating the view to render. The first stage is to cast the object in order to obtain the extra information:

ViewResult page = controller.Index() as ViewResult;

With the ViewResult object you can start verifying that the system is working correctly. One way to achieve this is via the ViewData property on the ViewResult object. ViewData is a collection that allows you to store weak and strongly typed data, and is used to pass data from the controller to the view for rendering. When using the strongly typed part of ViewData, you define a model that allows you to pass data back and forth via objects and properties.

To access the strongly typed object in your tests, you need to cast the ViewData property to your own ViewModel that you are planning to return; in this case the ViewModel is the ProductsMenuModel:

ProductsMenuModel model = page.ViewData.Model as ProductsMenuModel;

This is how you can verify that the correct data is being returned from the action. When the view renders, it will use the ViewData to obtain the results. Using your tests, you can obtain exactly the same data that the view would receive, allowing you to verify the controller is working as expected:

Assert.AreEqual(1, model.Products.Count);

The test is now in place and would look like the following:

[Test]
public void Index_Returns_All_Products_In_Database()
{
   List<Product> products = new List<Product>
               {
                   new Product
                       {
                           ID = 1,
                           Category = new ProductCategory {Description =
                                                           "Pizza"},
                           Name = "Classic Cheese",
                           Description = "Classic Cheese",

BasePrice = 8.00,
                                   Image = TestHelpers.GetDummyImage()
                               }
                       };
            stubProductRepository.Stub(r => r.GetAll()).Return(products);
            ProductsMenuController controller = new ProductsMenuController(
stubProductRepository);
            ProductsMenuModel model = controller.Index()
            .GetModel<ProductsMenuModel>();

            Assert.AreEqual(1, model.Products.Count);
        }

However this won't compile because the objects you are interacting with don't exist yet. After you have defined the test and outlined your expectations, the first stage is to get the project to a state where it can compile — this is just a case of creating the classes and methods without any implementation. You just want to compile at the moment.

After you can compile, you can execute your test to ensure that it fails as expected. As mentioned in Chapter 2, you want to see a failing test to provide confidence when you see the test finally pass. Many people say "It doesn't count if you don't see it fail first."

You can now create the implementation using your test as guidance. Remember, you are aiming to implement the minimum amount of code possible to make the test pass. In this case, you need to call a method on your Repository to obtain all the products, assign them to the model, and attach the model to your ViewData. The final implementation is shown next:

private readonly IProductRepository Repository;

public ProductsMenuController(IProductRepository repository)
{
    Repository = repository;
}
public ActionResult Index()
{
    ProductsMenuModel model = new ProductsMenuModel();
    List<Product> products = Repository.GetAll();
    model.Products = products;

    return View(model);
}

Now if you rerun the test, it should successfully pass.

The final stage of the process is to refactor your codebase. There are not many changes you could perform to improve your controller code because the code is already clean and legible. However, your test code could be made more readable.

Firstly, the test collection you create doesn't need to be part of the test. It would be more readable if you moved this initialization into a Setup method to keep the test focused on what it is testing. The SetUp method is run before each test and is the ideal position to place any set-up code, such as creating your test data collection. You can take the previous test, and simply extract the logic into the Setup method that has been attributed to indicate to nUnit that it should be executed:

List<Product> products;
[SetUp]
public void Setup()
{
    products = new List<Product>
                   {
                       new Product
                           {
                               ID = 1,
                               Name = "Classic Cheese",
                               Description = "Classic Cheese",
                               BasePrice = 8.00
                           },
                   };
}

Another concern with the test is around obtaining the model via the ViewData property. To gain access, you need to first cast the Index result into a ViewResult. You then need to cast the model into its concrete type of ProductsModelMenu. This additional logic causes you to lose focus on what is being tested, instead focusing your attention on this block of code. To keep the tests clean, this logic should be hidden from the test and moved into a different class that can deal with obtaining the model from the ViewData for you. To solve this, you created a generic extension method on the ActionResult object to handle the process of returning the model in the correct format:

public static class MVCTestExtensions
{
    public static T GetModel<T>(this ActionResult page) where T : class
    {
        return ((ViewResult) page).ViewData.Model as T;
    }
}

With this in place, to obtain the model for the ViewData you simply call the method on the results of your call to Index:

ProductsMenuModel model = controller.Index().GetModel<ProductsMenuModel>();

The GetModel method keeps your test code more streamlined and focused than it was previously, but also allows you to share this functionality between other tests. After you have completed the refactoring, your test and set-up code looks similar to the following:

[TestFixture]
public class ProductsMenuControllerTests
{
    List<Product> products;
    [SetUp]
    public void Setup()
    {
        products = new List<Product>

{
                              new Product
                                  {
                                       ID = 1,
                                       Name = "Classic Cheese",
                                       Description = "Classic Cheese",
                                       BasePrice = 8.00
                                  },
                           };
        }

        [Test]
        public void Index_Returns_All_Products_In_Database()
        {
            IProductRepository repository = MockRepository.GenerateStub
<IProductRepository>();
            repository.Stub(r => r.GetAll()).Return(products);

            ProductsMenuController controller = new ProductsMenuController(
repository);
            ProductsMenuModel model = controller.Index()
.GetModel<ProductsMenuModel>();

            Assert.AreEqual(1, model.Products.Count);
        }
    }

With your test data being created before each test in the set-up block you can share this amongst future tests and have the advantage that the test itself is clear and focused.

3.4.3.2. Creating ProductRepository

Even though you have proven that your controller action works as you expected, it still isn't very useful in terms of a real application. Because you have not implemented an object that inherits your IProductRepository you have no way of accessing the real data.

Within your application you are going to use NHibernate, which is an object relational mapping (ORM) framework. You are using a ORM for a number of reasons. Firstly, the framework will handle all of your database communication, creating and executing queries on your behalf, allowing you to code against strongly typed objects instead of handwritten SQL statements. This makes your code more flexible. Because the ORM handles this communication between the database and your domainusiness logic, it means it can be more easily isolated because your application is already being developed for different reasons. This isolation makes it much easier for you to create the repositories, which you can stub out and use to improve testability. If you didn't use an ORM and pay close attention to how you communicate with the database, you could have different parts of your code interacting with the database in different ways, making the system much harder to test.

NHibernate will provide you with the mapping to enable you to go from your domain object, for example Product, to your database table called Products. In the example, because you already have a legacy database, NHibernate will allow you to map your domain model and to a different database schema naming convention, allowing you to abstract and hide the underlying schema structure from the application. This allows you to maintain two views on the database without violating any design principals. For example, your Products table in the database will look like Figure 3-5.

Figure 3-5. Example Products table from the WroxPizza database

As you already have your domain model and your table, you simply need to create the mapping that links the two together. NHibernate's mapping takes the form of XML, yet a new project called Fluent NHibernate (http://fluentnhibernate.org) has been released that allows you to write the mappings as C# code instead of XML. This means that the mappings are now strongly typed, which results in compile time checking and are updated automatically when you perform your refactoring steps. With the mappings as XML, you do not have this level of flexibility.

Based on the structure, all the mapping classes will be stored within WroxPizza.Core.Data.Mapping. A class called ProductMap inherits from a generic class called ClassMap<T>, which is included within Fluent NHibernate. When you inherit from ClassMap, you simply replace the T with the domain class you are mapping to — in this case Product.

After referencing Fluent NHibernate, you can start to create your mapping to map your domain objects onto your database table and columns:

public class ProductMap : ClassMap<Product>

Fluent NHibernate follows a convention-over-configuration approach. By default, it will expect the class name to map to a table, and properties to map to columns. In this case the naming convention in our model and database are not the same. As such, you can use the WithTable() method to indicate the mapped table:

WithTable("Products");

Next you need to define your primary key. This is done by calling the ID method providing a lambda expression to define which property on the Product object you want to map. The second argument is the name of the column within the table:

Id(x => x.ID, "ProductId");

With the ID mapped, you simply need to map your remaining columns. Because the property and the column name are identical on the object and table you don't need to provide the second string argument defining the column name — it will simply be inferred. On the mapping, you'll add a Not Null constraint to indicate rules based on our data in the table:

Map(x => x.Name).CanNotBeNull();
Map(x => x.Description).CanNotBeNull();
Map(x => x.BasePrice).CanNotBeNull();

At this stage our mapping is complete. However you need to update the product model, because NHibernate requires all properties and methods on the model need to be marked as virtual. This is due to the way NHibernate handles lazy loading; it creates a proxy of the class for managing how and when to populate the collection.

The final stage is to implement the ProductRepository. For a basic Repository like this, most of the logic will be within the generic IRepository implementation. With this in mind, you created a generic NHibernateRepository<T> that inherits from IRepository<T>. ProductRepository will then inherit from NHibernateRepository<Product> and IProductRepository. This allows you to share the core functionality of a Repository amongst different repositories within your system. The implementation of the mapping is shown next:

public class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        WithTable("Products");
        Id(x => x.ID, "ProductId");
        Map(x => x.Name).CanNotBeNull();
        Map(x => x.Description).CanNotBeNull();
        Map(x => x.BasePrice).CanNotBeNull();
    }
}

For additional flexibility with the ProductRepository, I abstract away from the database configuration and created an IDbConfigure allowing me to pass in the relevant configuration when I construct the Repository. The configuration is handled by DefaultNHibernateConfig:

public class DefaultNHibernateConfig : IDbConfigure
{
    private Configuration configuration;
    private ISession currentSession = null;
    public DefaultNHibernateConfig()
    {
        configuration = new Configuration();
        configuration.AddAssembly(typeof(ProductRepository).Assembly);

        NHibernateModel model = new NHibernateModel();
        model.Configure(configuration);
    }

    public ISessionFactory GetSessionFactory()

{
        return configuration.BuildSessionFactory();
    }

    public ISession GetCurrentSession()
    {
        if (currentSession == null)
            currentSession = GetSessionFactory().OpenSession();

        return currentSession;
    }
}

The resulting ProductRepository implementation is next:

public class ProductRepository : NHibernateRepository<Product>, IProductRepository
{
    public ProductRepository(IDbConfigure factory) : base(factory)
    {}
}

As the Repository is tightly coupled to the database, there is little point in stubbing any section to unit test the implementation. Because of this, we felt that writing unit tests against this layer didn't add much value. Instead, you write a series of integration tests as you were developing the implementation. You also created a series of tests targeted at the NHibernate mapping files to ensure they are correct.

For more information on the integration tests, please refer to Chapter 4, which covers how you created the Tests.Integration project and tested the Repository.

3.4.3.3. Integrating IoC with StructureMap

At this point, you are starting to have a number of relationships and dependencies on different parts of the system. The following section describes how you can manage these dependencies within your ASP.NET MVC application. The easier your dependencies are to manage, the more decoupled your application will be, and as a result the easier it will be to test. This is why we feel IoC is an important concept for testability.

As described earlier in the chapter, the ProductsMenuController requires an object that implements IProductRepository to allow the controller to access the database. In turn, the ProductRepository implementation requires an IDbConfigure object for the database configuration. As such, to construct an instance of your controller the following code is required:

DefaultNHibernateConfig config = new DefaultNHibernateConfig();
ProductRepository repository = new ProductRepository(config);
ProductsMenuController controller = new ProductsMenuController(repository);

Even though this is messy from the point of view of your application's code, having a constructor dependency on the controller also means that the ASP.NET MVC Framework cannot automatically construct the controller. The answer is to use an IoC framework (as discussed in Chapter 2), which can construct instances of the objects and automatically resolve their dependencies. Luckily, ASP.NET MVC is IoC friendly, making it very easy to incorporate a framework into the pipeline.

The first task is to select a framework. Our recommendation is to use StructureMap (http://structuremap.sourceforge.net/) as your IoC framework. StructureMap has two main parts; first is the registration of dependencies with the second part being how it constructs the objects.

StructureMap needs some setup around the interfaces that exist and the concrete implementation that they should use. Although there is an auto mapping feature, manually defining them is equally as successful. This registration happens when the application first starts. In terms of an ASP.NET application, it starts when Internet Information Services (IIS) starts the appdomain for the website. When this occurs, the Application_Start() method is called in the Global.asax. At this point you need to set up StructureMap. This setup will be done within the Bootstrapper object within the Setup method:

Bootstrapper.Setup();

The Setup method simply initializes StructureMap and provides it with a subclass of the Registry class that configures the mapping:

public static void Setup()
{
    ObjectFactory.Initialize(c => c.AddRegistry(new WroxPizzaConfig()));
}

The WroxPizzaConfig object overrides the configure method that StructureMap calls during the AddRegistry stage. Within the method there are two important method calls. The first is ForRequestedType; this is the initial call to configure what happens when StructureMap is requested to construct an object with this type — for example, IProductRepository. When IProductRepository is requested, it looks at the value set by the second method. The second method is TheDefaultIsConreteType that defines the concrete implementation to use, in this case an instance of ProductRepository. This is the same for IDbConfigure where it provides an instance of DefaultNHibernateConfig. The initial configuration for StructureMap and the mappings are next:

internal class WroxPizzaConfig : Registry
        {
            protected override void configure()
            {
                ForRequestedType<IProductRepository>().TheDefaultIsConcreteType<
ProductRepository>();
                ForRequestedType<IDbConfigure>().TheDefaultIsConcreteType<
DefaultNHibernateConfig>();
            }
        }

StructureMap is a lot more powerful than simply creating objects, however, it can also provide this simple yet effective functionality.

With this mapping in place, StructureMap would now be able to construct instances of your controller. When a request comes in to the ProductsMenu Index page, ASP.NET will ask StructureMap for an instance of the type ProductsMenuController. StructureMap will analyze the constructer of the type and its arguments. When it sees IProductRepository it will attempt to create an instance, again looking at the constructor and parameter. Again, it will see IDbConfigure and provide an instance of DefaultNHibernateConfig before returning the new ProductRepository back to your controller.

While the IoC framework is now configured, you haven't told ASP.NET MVC about how to use the IoC framework and how it can construct objects. When ASP.NET MVC attempts to construct a controller, it will call into the ControllerFactory method that should know how to construct the controller instance. With the new decoupled nature, you can plug in your own ControllerFactory that can talk to your IoC framework to provide an instance of the requested controller.

The first task is to inform ASP.NET MVC that the controller factory exists. Within your Application_Start method in the Global.asax you simply call the SetControllerFactory method:

protected void Application_Start()
        {
            RoutesTable.RegisterRoutes(RouteTable.Routes);
            Bootstrapper.Setup();
            ControllerBuilder.Current.SetControllerFactory(
new StructureMapControllerFactory());
        }

The next stage is to create StructureMapControllerFactory. You have constructed the object within the WroxPizza.Core.Web.Setup namespace to keep everything centralized.

Your new StructureMapControllerFactory first needs to inherit from DefaultControllerFactory. This will provide you with the core functionality. To change the way you construct the actual instance of your controller you need to override the GetControllerInstance method.

The GetControllerInstance method has a parameter that defines the type of controller MVC is requesting. As such you can simply call GetInstance on ObjectFactory that maintains all the information for StructureMap and can create instances of objects requested by their type:

protected override IController GetControllerInstance(Type controllerType)
{
    if (controllerType == null)
        return null;

    return ObjectFactory.GetInstance(controllerType) as Controller;
}

As you add more controllers, this code doesn't need to be changed as it is flexible enough to cope. If you add a new dependency, you simply need to register it in your WroxPizzaConfig object.

3.4.3.4. Creating ProductsMenu/Index UI

Based on the previous section you've done, your business logic and data access are complete and you're ready to return all the products. You have taken a number of steps to structure your application in a more effective, testable fashion to allow you to add new features going forward. However, you have one major step missing — the UI. Your business logic is complete and tested, however your poor users still cannot see anything.

You need to create a view to display your model and associated data. The view engine you are going to use is ASP.NET WebForms. Following the MVC structure, as shown in Figure 3-6, you need a folder called ProductsMenu that matches your Controller name as well as a page that will make your Action Method on the controller — in this case, index.aspx.

Figure 3-6. Views and controllers in solution

Your ASP.NET view should also be attached to the ASP.NET Master Page Site.aspx. At the moment this is the default ASP.NET MVC blue template that you can modify at a later date to fit in with the style of website you want.

In terms of how you developed your controller, you have a strongly typed model containing a collection of all the products you want to display. This is stored in an object of type ProductsMenuModel. For your view to access this object, the view page needs to inherit from the generic ViewPage<T> page. As such, the page directive will be the following:

<%@ Page Title="" Language="C#" MasterPageFile="∼/Views/Shared/Site.Master"
    AutoEventWireup="true"
    Inherits="System.Web.Mvc.ViewPage<ProductsMenuModel>" %>

You can now access the ViewModel object via the variable model:

<% foreach (var product in Model.Products) { %>
        <%=product.Name %>
        <%=product.Description %>
        <%=product.BasePrice %>
<% } %>

The previous code will successfully output the items from the menu. However, instead of the products being listed as a list, they should be side-by-side. To do this you need to have alternative styles for your rows of products. When you have different styles for a pair of rows, you can use CSS to align them side-by-side on the screen. For you to determine which CSS style to use for each side of the list, you need some additional logic that you'll want to test to ensure it works correctly.

With MVC, there are various helper methods included on an object accessed via the Html variable, which is of type HtmlHelper. By using extension methods in C# 3.0, you can extend this object to provide additional functionality while also fitting into the MVC approach to help readability. As these are extension methods, they will be coded in the MVCExtensions class, with the unit tests in the class MVCExtensionsTests.

To test the methods on the HtmlHelper, you need an instance of the actual HtmlHelper object. To create an instance of the HtmlHelper method, you need to provide a ViewContext and IViewDataContainer object. Using RhinoMocks, you can easily generate stub objects to use as parameters on the constructor. In order to keep the test code as clean as possible, there should be a helper method that hides this stubbing and construction:

public static HtmlHelper CreateHtmlHelper()
        {
            ViewContext context = MockRepository.GenerateStub<ViewContext>();
            IViewDataContainer container = MockRepository.GenerateStub<
IViewDataContainer>();
            return new HtmlHelper(context, container);
        }

In your Setup method, you can gain an instance of your HtmlHelper:

[SetUp]
public void Setup()
{
    helper = MockHelper.CreateHtmlHelper();
}

To create alternating styles, you need to provide an even number (0) for a normal-row to be returned. If you provide an odd number (1), then you should expect the alternative style to be returned. This is how you create the side-by-side styles for all your products. This logic is represented in the two test methods shown next:

[Test]
public void GetRowClass_Returns_Normal_For_Even_Number()
{
    string rowClass = helper.GetRowClass(0);
    Assert.AreEqual("normal-row",rowClass); //CSS Style
}
[Test]
public void GetRowClass_Returns_Alt_For_Odd_Number()
{
    string rowClass = helper.GetRowClass(1);
    Assert.AreEqual("alternate-row", rowClass); //CSS Style
}

Your implementation is then very simple as shown next:

public static string GetRowClass(this HtmlHelper helper, int rowIndex)
{
    return rowIndex % 2 == 0 ? "normal-row" : "alternate-row";
}

Although this might seem over the top for such simple logic, the reason for the tests is to provide the documentation and verification that it does work as expected. The constantly writing of the tests also keeps you in the TDD mindset, allowing it to become more natural.

The result is that your code now looks similar to the following, with your main complex part in a separate class with associated unit tests:

<% for (int i = 0; i < Model.Products.Count; i++) { %>
         <div class="<%=Html.GetRowClass(i) %>">
            <%= Html.Encode(Model.Products[i].Name) %><br />
            <%= Html.Encode(Model.Products[i].Description)%><br />
            <%= Model.Products[i].BasePrice%>
        </div>
<% } %>

In both examples, your view is starting to get messy and confusing. It is difficult to see which part of the code is the main page, which part handles displaying all the products, and which part just handles displaying the single product on the screen. To solve this, you can take advantage of user controls and being able to render partial sections of content. By breaking the different sections of your UI into user controls, you can make the view more readable and open up the possibilities of reusing the actual layout in other parts of the application. This isn't done to improve testability directly, but to improve the maintainability and readability of the code. As a result, issues and bugs should become more obvious as the code is cleaner.

Now, when you output your grid you call the RenderPartial method. As arguments, you provide the user control that you want to render (in this case ProductGrid). The second argument you provide is the list of products that you want to be included on the grid:

<div class="Products">
    <% Html.RenderPartial("ProductGrid", Model.Products); %>
</div>

Within the ProductGrid control, you have the code to output the grid. Two things to note, first your model is now a strongly typed List<Product> that you provided from the Model.Products variable. The second point is that your product is rendered via the use of the ProductItem user control. You should call this multiple times, once for each product:

<% for (int i = 0; i < Model.Count; i++) { %>
         <div class="<%=Html.GetRowClass(i) %>">
            <% Html.RenderPartial("ProductItem", Model[i]); %>
        </div>
<% } %>

Your ProductItem user control then simply outputs the required information to be displayed within the product grid:

<div class="productDesc">
           <%= Html.Encode(Model.Name) %><br />
           <%= Html.Encode(Model.Description) %><br />
           <%= Model.GetPrice() %>
</div>

Notice your calculation for GetPrice is in a method on a Product domain model, which means that it can be unit tested.

The implementation of GetPrice() is very simple, as it returns the BasePrice variable as a string with the dollar sign prefixed:

public virtual string GetPrice()
{
    return "$" + BasePrice;
}

As a result, you can create unit tests to implement this functionality.

[TestFixture]
public class ProductTests
{
    [Test]
    public void GetPrice_Returns_Price_As_String_With_Dollar_Symbol()
    {
        Product p = new Product();
        p.BasePrice = 4.99;

        Assert.AreEqual("$4.99", p.GetPrice());
    }
}

You now have your page in place, which renders multiple user controls to display the different products. The final step is to design your master page. This is the HTML around your content that will be shared among the other pages in the site to provide a consistent view.

The structure of the project now looks like Figure 3-7.

The only thing left is to tell the application the real database to use to serve data from. As mentioned before, your unit tests are running off the App.Config to identify the NHibernate settings. Within a web application, you use the web.config where you can place your NHibernate configuration that you want your application to use. Within the Config section of the web.config, you include a section name:

<configSections>
    <section name="hibernate-configuration"
             type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate"/>
....
</configSections>

Figure 3-7. Final product structure

Underneath you include your NHibernate configuration, the same as you did for your unit tests, however pointing at a SQL Server 2005 instance:

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.connection_string">
     Data Source=(local);initial catalog=WroxPizza;Integrated Security=True;
    </property>
    <property name="connection.provider">
     NHibernate.Connection.DriverConnectionProvider
    </property>
    <property name="dialect">
     NHibernate.Dialect.MsSql2005Dialect
    </property>
    <property name="connection.driver_class">
     NHibernate.Driver.SqlClientDriver
    </property>
    <property name="connection.release_mode">
     on_close
    </property>
    <property name="show_sql">
     false
    </property>
  </session-factory>
</hibernate-configuration>

With everything in place, your application should work as expected. The final stage is to ensure the database has been created and populate it with test data, for the example in Figure 3-8 you used a tool from Red Gate called SQL Data Generator (http://www.red-gate.com/products/SQL_Data_Generator/index.htm).

If you visit the ProductsMenu Index page, you see a list of products in a similar fashion to Figure 3-8.

Figure 3-8. The Wrox Pizza Shop Products Menu

As you might have noticed, you didn't unit test all your UI — but you tested some logic such as the GetRowClass method. The aim should be to keep the UI as simple and maintainable as possible; breaking complex logic into user controls helped readability and kept it simpler, while moving logic into separate classes to support testability.

To verify that the UI is working as expected in an end-to-end process, you will have a set of UI tests that will be covered in Chapter 5.

3.4.4. Feature 2: Adding Categories

The first feature was to list all the products on the page. The second feature is to have different categories for products and only display certain products for a particular category.

To add this new functionality you need to modify various parts of your application. First of all, the controller will need to return a list of categories and will also need to take a category and return only the certain products within that category. Your ProductRepository will need to be modified to allow you to filter our query. Finally, your UI will need to be modified to display links to the different categories together with a page to show the filtered list of products.

The first change you need to make is to the controller in order to return a list of categories. When you access the Index page, you want the list of categories to be attached to the ProductsMenuModel that you can then use in the UI. The test you are aiming to make pass is as follows. The main points of this are that you are stubbing your implementation for the Repository; after that you verify that the categories are returned as expected based on the products' list you created in the set-up block:

[Test]
        public void Index_Can_Get_Categories_As_List_Of_Strings()
        {
            IProductRepository repository = MockRepository.GenerateStub<
IProductRepository>();
            repository.Stub(r => r.GetAll()).Return(products);

            ProductsMenuController controller = new ProductsMenuController(
repository);
            ProductsMenuModel model = controller.Index()
.GetModel<ProductsMenuModel>();

            Assert.AreEqual(1, model.Categories.Count);
            Assert.AreEqual("Pizza", model.Categories[0].Description);
        }

In terms of implementation, because you already have your products returned from the database, you can simply use these products to form the base for obtaining the different categories available. You could have used the database and requested the list, but it may have performance issues.

Within your Index you need to add a new method that will return a list of ProductCategory. ProductCategory is a domain object that maps onto a table without your database and is referenced by your product. To keep the code clean, you need an additional method called GetCategoriesFromProductList that will take a list of products and return the categories:

[Test]
       public void GetCategoriesFromProductList_Should_Return_Pizza()
       {
            ProductsMenuController controller = new ProductsMenuController(
stubProductRepository);
            List<ProductCategory> categories = controller
.GetCategoriesFromProductList(products);
            Assert.AreEqual("Pizza", categories[0].Description);
            Assert.AreEqual(1, categories.Count);

}

The implementation for this is as follows.

private List<ProductCategory> GetCategoriesFromProductList(
List<Product> products)
        {
            List<ProductCategory> list = new List<ProductCategory>();
            foreach (var product in products)
            {
                    list.Add(product.Category);

}

            return list;
        }

You then need to add a new property onto the ProductsMenuModel to store the categories that are populated with the value of the previous method call:

public ActionResult Index()
{
    ProductsMenuModel model = new ProductsMenuModel();
    List<Product> products = Repository.GetAll();
    model.Products = products;

    model.Categories = GetCategoriesFromProductList(products);
    return View(model);
}

However, this implementation has one bug. If you have two products in the same category, then the category will be returned twice. You want the list to be unique as this will be used in your navigation system on the web page. The first stage is to write a test that highlights the bug and defines the desired behavior:

[Test]
        public void GetCategoriesFromProductList_Returns_No_Duplicate_Categories ()
        {
            products.Add(new Product
            {
                ID = 2,
                Category = new ProductCategory {Description = "Pizza"}, //Duplicate
                Name = "Classic Four Cheeses",
                Description = "Classic Four Cheeses",
                BasePrice = 9.00
            });

            ProductsMenuController controller = new ProductsMenuController(
stubProductRepository);
            List<ProductCategory> categories = controller
.GetCategoriesFromProductList(products);
            Assert.AreEqual(1, categories.Count);
        }

On the first line, you are adding an additional product to your base test data. This helps define the specific test while keeping the other tests generic. If this was going to be regularly required, then you might want to look at other ways of creating test data such as Object Mothers (discussed in Chapter 5). Now that you have the failing test, you can fix the bug and make the test pass.

In terms of changes to your UI, at the top of your index page, your categories will be rendered via a separate user control (again to keep your UI clean):

<div class="menu">
    <% Html.RenderPartial("CategoriesMenu", Model.Categories);%>
</div>

The user control will loop around and output a link:

<%  foreach (var s in Model) { %>
    <%=Html.CreateShowLink(Html.Encode(s.Description))%> |
<% }%>

Similar to how you extended the HtmlHelper object before, you have done the same with your CreateShowLink. This takes in the description and constructs the correct link to your Show page to show all the products in the category:

[Test]
        public void CreateShowLink_Returns_ConstructedUrl_String_With_Desc_As_
LinkText()
        {
            string t = h.CreateShowLink("Test");
            Assert.IsNotNullOrEmpty(t);
            Assert.IsTrue(t.Contains("Test"));
        }

        public static string CreateShowLink(this HtmlHelper html, string text)
        {
            return html.ActionLink<ProductsMenuController>(c => c.Show(text), text);
        }

If you launch the application, then your category links will appear like in Figure 3-9.

Figure 3-9. Category links

With the links being rendered at the top of the page, you now need to make a page that just displays those products. Your users can now visit the Show page, providing the category as a parameter to the page. The next step is to implement the Show action method and view. Again, you stub your IProductRepository, however this time you stub a new method called GetProductsByCategory. This takes a category as a string, in this case pizza. This should return a list of products which are within the category "pizza." In this test, you want the GetProductsByCategory to return our Products test data collection.

As you did before, in our test you call the Show method and then obtain the ViewData model from the result. After you verify that only one product was returned:

[Test]
        public void Show_Return_Product_For_a_Single_Category()
        {
            string category = "Pizza";
            IProductRepository repository = MockRepository.GenerateStub<
IProductRepository>();
            repository.Stub(r => r.GetProductsByCategory(category))
.Return(products);

            ProductsMenuController controller = new ProductsMenuController(
repository);
            ProductsMenuModel model = controller.Show(category)
.GetModel<ProductsMenuModel>();

            Assert.AreEqual(1, model.Products.Count);
        }

Although this test covers the core functionality, there is only have one item in your collection — as such you are not filtering the list and might be confusing to readers of the test. To provide more clarity, you can add an additional test:

[Test]
        public void Show_Only_Returns_Products_For_a_Single_Category_When_Two_Exist()
        {
            products.Add(new Product
            {
                ID = 2,
                Category = new ProductCategory { Description = "Starter" },
                Name = "BBQ Chicken Wings",
                Description = "4x BBQ Chicken Wings",
                BasePrice = 4.00
            });

            string category = "Pizza";

            IProductRepository repository = MockRepository.GenerateStub<
IProductRepository>();
            repository.Stub(r => r.GetProductsByCategory(category))
                                  .Return(products.Where(p => p.Category
.Description == category).ToList());

            ProductsMenuController controller = new ProductsMenuController(
repository);

ProductsMenuModel model = controller.Show(category)
.GetModel<ProductsMenuModel>();

            Assert.AreEqual(1, model.Products.Count);
        }

Although this test is longer, it adds value to the overall suite. A new product is added to your base test data. You then use LINQ to Objects to filter your expected return data based on the category description. This should make it very easy to understand what you expect to happen.

In terms of the implementation, all you need to do is create your ProductsMenuModel and attach the results from your Repository:

public ActionResult Show(string category)
{
    ProductsMenuModel model = new ProductsMenuModel();
    model.Products = Repository.GetProductsByCategory(category);
    return View(model);
}

The new method, GetProductsByCategory, will only be used by your ProductRepository. Because you have the IProductRepository already in place, you can simply add the method to this interface without affecting your other repositories:

public interface IProductRepository : IRepository<Product>
{
    List<Product> GetProductsByCategory(string category);
}

With your Repository tests and implementation in place, you need to implement your Show view.

Your view simply needs to output all the products reusing the ProductItem control you built earlier. The first approach is to simply iterate over the Products collection and render the partial control in your div tags:

<% foreach (Product p in Model.Products) { %>
   <div class="normal-row"><%=Html.RenderPartial("ProductItem", p) %> </div>
<% } %>

However, this starts to become difficult to read with the multiple opening and closing ASP.NET tags. Remember, you want to keep your code as clean as possible. By creating another extension method, called WithDiv, you can output a div with a particular Partial control rendered inside, in the same way as shown previously. The advantage of this is that you only have a single set of open and close tags. On the WithDiv method, the first parameter is the style to attach to the div, while the second parameter is an action that should be invoked to produce the content. In this example, the action is to render the partial method:

<%
    foreach (Product p in Model.Products)
        Html.WithDiv("normal-row", () => Html.RenderPartial("ProductItem", p));
%>

This method can also be unit tested to verify it works as you hope. In the first test, you want to verify that the WithDiv method correctly outputs the div with the style attached. You need to mock the HttpResponse as this is where you need to write content to, in order for the data to be returned to the user for rendering by their web browser. By using a mock you can verify that the correct calls were made with the correct data, and as such verify that the test passes:

[Test]
        public void WithDiv_Writes_Div_Tags()
        {
            HttpContextBase httpContext = MockRepository.GenerateStub<
HttpContextBase>();
            HttpResponseBase httpResponseBase = MockRepository.GenerateMock<
HttpResponseBase>();
            httpContext.Stub(c => c.Response).Return(httpResponseBase);

            httpResponseBase.Expect(r => r.Write("<div class="styleClass">"));
            httpResponseBase.Expect(r => r.Write("</div>"));

            HtmlHelper helper = MockHelper.CreateHtmlHelper(httpContext);

            string t = string.Empty;
            helper.WithDiv("styleClass", () => t = string.Empty);

            httpResponseBase.VerifyAllExpectations();
        }

The second test, verifies that the action was called correctly. An action is a delegate, which means they are easy to test. As the action, you simply set a variable to true that you can test against in order to know if the call was successful. When you use the method in your main system, you can be confident that the action will be called as expected:

[Test]
        public void WithDiv_Executes_Action()
        {
            HttpContextBase httpContext = MockRepository.GenerateStub<
HttpContextBase>();
            HttpResponseBase httpResponseBase = MockRepository.GenerateMock<
HttpResponseBase>();
            httpContext.Stub(c => c.Response).Return(httpResponseBase);

            HtmlHelper helper = MockHelper.CreateHtmlHelper(httpContext);

            bool called = false;
            helper.WithDiv("row", () => called = true);

            Assert.IsTrue(called);
        }

You have created two tests because they are verifying two different things. The first test is verifying that the correct HTML is written to the correct output. The second test is verifying that the action is called correctly. By having them as two separate tests, you can verify that each logical section is working.

When it comes to the implementation, the tests have already defined your expectations, so you simply need to fill in the gaps:

public static void WithDiv(this HtmlHelper helper, string style,
Action action)
        {
            helper.Write(string.Format("<div class="{0}">", style));
            action();
            helper.Write("</div>");
        }
        public static void Write(this HtmlHelper helper, string text)
        {
            helper.ViewContext.HttpContext.Response.Write(text);
        }

With this in place your web page works as you want it to. However, you still have a problem with your URL. The link you created earlier results in the URL looking similar to /ProductsMenu/Show?category=Pizza. With MVC, you want a cleaner looking URL that is more similar to /ProductsMenu/Show/Pizza. This can be solved by modifying your Routing table.

In your RouteSetup object, you need to add a new entry above the default route. In the new entry, you define that for the controller ProductsMenu, when the action Show is called, the category parameter should be included as an additional slash and parameter instead of as an entry on the querystring:

routes.MapRoute(
                    "ShowProductCategory",
                    "{controller}/Show/{category}",
                    new { controller = "ProductsMenu", action = "Show",
category = "" }
                );

When you have your products being listed, it would be nice to give them a header, the logical choice is to use the current category. The test for this simply verifies the CurrentCategory property is what you expected based on your test products list — in this case pizza:

[Test]
        public void Show_Returns_The_Category_As_A_Property()
        {
            string category = "Pizza";
            IProductRepository repository = MockRepository.GenerateStub<
IProductRepository>();
            repository.Stub(r => r.GetProductsByCategory(category))
.Return(products);

            ProductsMenuController controller = new ProductsMenuController(
repository);
            ProductsMenuModel model = controller.Show(category)
.GetModel<ProductsMenuModel>();

            Assert.AreEqual(category, model.CurrentCategory);
        }

Within your Show method, you simply assign the parameter to the property:

model.CurrentCategory = category;

You can then use this property within your UI:

<h2><%= Model.CurrentCategory %></h2>

The reason you have a unit test for such a small piece of functionality is all about Test Driven Development. No matter how small, a test should still be written to cover the implementation and verify it works as expected.

3.4.5. Feature 3: Adding Items to the Shopping Cart

Now that you have your products displayed on the screen, the next stage is to add a product into the basket that the user can then proceed and purchase.

The aim is that you will allow users to add multiple products into a shopping cart. This cart is persisted across sessions using their username as an identifier. This means the next time they visit the site, the cart will still be available. When the user is happy with the products in the cart, they should be able to proceed and complete their purchase. Other features include the ability to update the shopping cart quantity and remove unwanted products.

To handle the basketshoppingcart you need to assign the responsibility. In a similar way to your Products menu, you are going to need a ShoppingCartController to support your shopping cart implementation. The most complex part of the implementation is around adding an item to the basket. This is where you will start.

The idea is that you will have a link on your menu that will add the particular product to the basket. The link will be a button that will submit a form to a particular action on your ShoppingCartController. Within your ProductItem control, wrap your existing code into a BeginForm. As part of this, provide an action method that should be called when the form is submitted. In this case, you need to send the request to the AddToBasket method on the ShoppingCartController. So that the controller knows which product to add to the cart, you need to provide the Product ID as an argument. From a testability point of view you can replicate exactly how the form will submit requests to the controller, meaning your tests will accurately reflect the functionality.

The final argument is the ID of the style sheet to use. This style sheet will make the button look like a hyperlink instead of a button:

<% using(Html.BeginForm<ShoppingCartController>(p => p.AddToBasket(Model.ID))) { %>
           <%= Html.Encode(Model.Name) %><br />
           <%= Html.Encode(Model.Description) %><br />
           <%= Model.GetPrice() %>
           <%= Html.SubmitButton("Add to basket", "Add to basket",
new {id = "submit"}) %>
<% } %>

You can now start implementing the method by using TDD. The first task is to get the shopping cart for a user. You will do this by requesting the cart from your IShoppingCartRepository implementation as shown next:

public interface IShoppingCartRepository : IRepository<ShoppingCart>
{
    ShoppingCart GetCart(string username);
}

Again, the implementation of the concrete Repository will be discussed in Chapter 4, but for now, you can simply mock this. GetCart will return your cart and that's all the test needs to worry about.

The first test is to verify that the 'Add To Basket' method under test correctly calls into your IShoppingCartRepository. To write this you need to mock your Repository as done before. After this, you call the method with a productId as a parameter and verify that your expectations occurred:

int PRODUCT_ID = 1;
        [Test]
        public void If_Cart_Already_Exists_Then_AddToBasket_Should_Use_It()
        {
            ShoppingCart shoppingCart = new ShoppingCart();
            IShoppingCartRepository shoppingCartRepository = MockRepository
.GenerateMock<IShoppingCartRepository>();
            shoppingCartRepository.Expect(r => r.GetCart()).Return(shoppingCart);

            ShoppingCartController controller = new ShoppingCartController(
shoppingCartRepository);
            controller.AddToBasket(PRODUCT_ID);
            shoppingCartRepository.VerifyAllExpectations();
        }

Once you have your cart object, you need the product from the database. You can reuse your existing IProductRepository to gain this. In a similar fashion, verify that the Repository was correctly called:

[Test]
        public void AddToBasket_Pulls_Product_From_Database_Based_On_ID()
        {
            Product product = new Product { ID = PRODUCT_ID, Name = "ProductName",
Description = "ProductDesc" };

            IShoppingCartRepository stubShoppingCartRepository = MockRepository
.GenerateStub<IShoppingCartRepository>();

            IProductRepository mockProductRepository = MockRepository.GenerateMock<
IProductRepository>();

            productRepository.Expect(r => r.Get(PRODUCT_ID)).Return(product);

            ShoppingCartController controller = new ShoppingCartController(
stubShoppingCartRepository, mockProductRepository);
            controller.AddToBasket(PRODUCT_ID);
            mockProductRepository.VerifyAllExpectations();
        }

To keep our tests clean and more focused, some of your set-up logic can be moved. By having the construction done in the setup, your tests are left to focus on getting your expectationsstubs and verifying that everything worked as expected:

ShoppingCart shoppingCart;
        Product product;
        IProductRepository stubProductRepository;
        IShoppingCartRepository stubShoppingCartRepository;
        [SetUp]
        public void Setup()
        {
            shoppingCart = new ShoppingCart();
            product = new Product { ID = PRODUCT_ID, Name = "ProductName",
Description = "ProductDesc" };

            stubShoppingCartRepository = MockRepository.GenerateStub<
IShoppingCartRepository>();
            stubProductRepository = MockRepository.GenerateStub<
IProductRepository>();
        }

This allows us to refactor our initial test to look more like this, which I'm sure you would agree is more readable:

[Test]
        public void AddToBasket_Pulls_Product_From_Database_Based_On_ID()
        {
            IProductRepository mockProductRepository = MockRepository.GenerateStub<
IProductRepository>();
mockProductRepository.Expect(r => r.Get(PRODUCT_ID)).Return(product);

            ShoppingCartController controller = new ShoppingCartController(
stubShoppingCartRepository, mockProductRepository);
            controller.AddToBasket(PRODUCT_ID);
            mockProductRepository.VerifyAllExpectations();
        }

The reason you created the Product Repository mock inside the test is that mocks are only used in a small number of tests, while stubs are used in the majority:

public ActionResult AddToBasket(int productID)
{
    Product product = ProductRepository.Get(productID);

    ShoppingCart cart = Repository.GetCart();
    return View();
}

Now that the AddToBasket has the cart and a product as shown next, we simply need to join the product and cart together.

Because the tests are no longer verifying the interactions, the stub implementations, already created in the Setup method, are set for how the objects should behave. This test verifies that the product is correctly added to the ShoppingCart object, which was created in the Setup method:

[Test]
        public void Cart_Should_Contain_ShoppingCartItem_With_Product_Attached()
        {
            stubProductRepository.Stub(r => r.Get(PRODUCT_ID)).Return(product);

            stubShoppingCartRepository.Stub(r => r.GetCart()).Return(shoppingCart);

            ShoppingCartController controller = new ShoppingCartController(
stubShoppingCartRepository, stubProductRepository);
            controller.AddToBasket(PRODUCT_ID);
            Assert.AreEqual(product, shoppingCart.Items[0].Product);
        }

In order to implement this functionality, you need to add an additional method onto our ShoppingCart model. As such, you need a test that will define the functionality required in order to be able to add items into the basket:

[TestFixture]
public class ShoppingCartTests
{
    [Test]
    public void AddItems_Adds_Shopping_Cart_Item_To_Collection()
    {
        ShoppingCart cart = new ShoppingCart(username);
        cart.AddItem(new Product { ID = 1, BasePrice = 1 });
        Assert.AreEqual(1, cart.Items.Count);
    }
}

This test verifies that the AddItem method does in fact add an item into the Items collection. With this in place, you can use your AddItem method in the same way in our AddToBasket method.

The final stage is to save the cart back to the Repository, and hence, back to your database for future use. In this test, simply set the expectations on our mock to define that you expect a call made to the SaveOrUpdate() method:

[Test]
        public void AddToBasket_Saves_Cart_Back_To_Repository()
        {
        IShoppingCartRepository mockShoppingCartRepository = MockRepository
.GenerateMock<IShoppingCartRepository>();
            mockShoppingCartRepository.Expect(r => r.SaveOrUpdate(shoppingCart))
.Constraints(Is.TypeOf(typeof(ShoppingCart)).Return(shoppingCart);

        ShoppingCartController controller = new ShoppingCartController(
mockShoppingCartRepository, stubProductRepository);
            controller.AddToBasket(PRODUCT_ID);
            mockShoppingCartRepository.VerifyAllExpectations();
        }

In the previous test, you add a constraint onto your expected call. These constraints simply define some additional rules about what to expect. In this case it is just a particular type; however, they can be complex rules such as defining particular data within a property on the object (for example, Property.IsNotNull("Username")). At this point, your implementation should look like this:

public ActionResult AddToBasket(int productID)
{
    Product product = ProductRepository.Get(productID);

    ShoppingCart cart = Repository.GetCart();
    cart.AddItem(product);

    Repository.SaveOrUpdate(cart);
    return View();
}

However, there is a problem. After you have added the item you will be redirected to a view called AddToBasket. Ideally, you want to be redirected to a particular page that will show the cart itself. Again, writing test, first you verify that the page goes to the correct location. By casting the result of the AddToBasket to a RedirectToRouteResult you can test to verify that the correct Action was called, in this case Show:

[Test]
        public void After_Adding_Item_To_Basket_It_Redirects_To_Cart()
        {
            ShoppingCartController controller = new ShoppingCartController(
shoppingCartRepository,productRepository);
            RedirectToRouteResult view = controller.AddToBasket(PRODUCT_ID) as RedirectToRouteResult;

            Assert.AreEqual("Show", view.RouteValues["action"]);
        }

Within your AddToBasket method, instead of returning View(), you return RedirectToAction("Show").

With your happy path complete, you need to implement edge-case scenarios. The first being what happens if the cart doesn't already exist. In the case where a cart doesn't exist, you want your Repository to return null. When this happens, you expect a new cart to be created and used as normal without any problems, and then saved back to the database for future use.

Your stub object represents this. First you define that you expect a call to be made to your Repository that will return null. Then you define that you expect a call to be made to the SaveOrUpdate method with an additional constraint saying that the object should be a ShoppingCart object. After you call AddToBasket from your test, you can verify that the expectations were met:

[Test]
        public void If_Cart_Does_not_Exist_Then_Null_Should_Be_Returned_And_A_Cart_
Created()
        {
            IShoppingCartRepository mockShoppingCartRepository = MockRepository
.GenerateMock<IShoppingCartRepository>();

mockShoppingCartRepository.Expect(r => r.GetCart()).Return(null);

            mockShoppingCartRepository.Expect(r => r.SaveOrUpdate(shoppingCart))
                        .Constraints(Is.TypeOf(typeof(ShoppingCart)))
                        .Return(shoppingCart);

            ShoppingCartController controller = new ShoppingCartController(
mockShoppingCartRepository, stubProductRepository);
            controller.AddToBasket(PRODUCT_ID);

            mockShoppingCartRepository.VerifyAllExpectations();
        }

You now have your basket working, with items being saved into either a new or existing shopping cart.

The final requirement is that all the shopping carts should be associated with a username. To get the username, you need an additional service to obtain the current username from the ASP.NET membership provider. You need to create a service that will wrap this functionality in order to make it testable. This service will implement the ICredentialsService interface that has a single method that returns the username. By having your own CredentialsService you don't need to be dependent upon the built-in ASP.NET membership provider. It allows you to mockstub the service, which isn't possible with the built-in provider. The implementation details for the service will be discussed in Chapter 4:

public interface ICredentialsService
{
   string GetUsername();
}

The test now ensures that the controller accesses the service; you mock object the ICredentialsService, setting it to return the username as a string. The test then verifies that this call was made:

private string USERNAME = "TestUser";
        [Test]
        public void When_Creating_A_Cart_It_Should_Ask_Credentials_Provider_For_Username()
        {
            ICredentialsService mockCredentialsService = MockRepository
.GenerateMock<ICredentialsService>();
            mockCredentialsService.Expect(r => r.GetUsername()).Return(USERNAME);

            ShoppingCartController controller = new ShoppingCartController(
stubShoppingCartRepository, stubProductRepository, mockCredentialsService);
            controller.AddToBasket(PRODUCT_ID);

            mockCredentialsService.VerifyAllExpectations();
        }

To provide the controller with access to the CredentialsService, you should use constructor injection. However, you will need to revisit the other tests that also use the controller, which means that the other tests also required a CredentialsService. These tests simply want a stub ICredentialsService object that will always return a particular username. To keep the code as clean as possible you should use a helper method to provide this functionality:

public static ICredentialsService CreateCredentialsService(string username)
{

ICredentialsService credentialsService = MockRepository.GenerateStub<
ICredentialsService>();
            credentialsService.Stub(r => r.GetUsername()).Return(USERNAME);
            return credentialsService;
        }

As part of this change, IShoppingCartRepository and the GetCart method was modified to accept the username to use in the query:

public interface IShoppingCartRepository : IRepository<ShoppingCart>
{
    ShoppingCart GetCart(string username);
}

As a result, the mock objects were changed to reflect this:

mockShoppingCartRepository.Expect(r => r.GetCart(USERNAME))
.Return(shoppingCart);

Going back and changing your tests is something that will occur during their lifetime. As long as you keep the changes small and targeted, the impact should be minimal. Constantly running the tests can help identify changes and failures faster, which should also result in the fixes being much quicker to make.

Finally you are constructing your own shopping cart object with some defaults that you should test to ensure they're correct to be set correctly. In your WroxPizza.Tests.Unit.Model.ShoppingCartTest you have your tests for the model itself. You simply want one test that will verify that the defaults are set correctly as shown next:

[Test]
public void Default_Object_Has_Date_NoItems_And_Username_Attached()
{
    ShoppingCart cart = new ShoppingCart(USERNAME);

    Assert.AreEqual(USERNAME, cart.Username);
    Assert.AreEqual(0, cart.Items.Count);
    Assert.AreEqual(DateTime.Now, cart.Created);
}

While the test looks straight forward it will never pass. The reason is because the Created date on the cart will never be the current time when the check is made. In fact, the tests don't know what time it might be. You want your tests to be repeatable and deterministic — having a date based on the system clock causes problems because the test becomes non-deterministic. You need a way to freeze time within your unit tests. The answer is to create a SystemTime class (http://ayende.com/Blog/archive/2008/07/07/Dealing-with-time-in-tests.aspx). The class will have a C# 3.0 function attached to return the current DateTime. On the SystemTime object, there will be a method called Now(). When this is called, it will return the result of DateTime.Now:

public static class SystemTime
{
    public static Func<DateTime> Now = () => DateTime.Now;
}

This doesn't sound like it will solve the problem, however the function can be redefined at runtime. In your test setup, you can redefine SystemTime.Now to return a predetermined date instead of the DateTime.Now. This means you can now handle dates in your unit tests as long as your code uses SystemTime:

DateTime testDate;
[SetUp]
public void Setup()
{
    testDate = new DateTime(2000, 1, 1);
    SystemTime.Now = () => testDate;
}

With this in place, the date the application uses will always be 1/1/2000 during your unit tests, while your live system will use the correct DateTime.Now value.

At this point you can add products to your basket, but you have no way to show them. If you remember, your add method will redirect to your Show action after it has completed; this action will result in a page being displayed to the user.

The first test you need to write for your show method is actually obtaining your shopping cart when you first visit the page. As with your Products menu, you have a ShoppingCartModel that will have the shopping cart as a property:

[Test]
        public void Cart_Action_Gets_Cart_For_User()
        {
            shoppingCartRepository.Stub(r => r.GetCart(USERNAME))
.Return(shoppingCart);

            ShoppingCartController controller = new ShoppingCartController(
shoppingCartRepository, productRepository,
MockHelper.CreateCredentialsService(USERNAME));

            ShoppingCartModel model = controller.Show().
GetModel<ShoppingCartModel>();
            Assert.IsNotNull(model);
        }

Because you already have the core functionality in place testing, your implementation is very simple.

public ActionResult Show()
{
    ShoppingCartModel model = new ShoppingCartModel();
    model.Cart = CreateOrGetCart();

    return View(model);
}

You can reuse the CreateOrGetCart() method extracted from your AddToBasket implementation.

private ShoppingCart CreateOrGetCart()
{

ShoppingCart cart = Repository.GetCart(CredentialsService
.GetUsername());

            if(cart == null)
                cart = new ShoppingCart(CredentialsService.GetUsername());
            return cart;
        }

After extracting the CreateOfGetCart method, you could return and add some additional unit tests focused on this particular method. However, the tests already provided good coverage on this block of code and as such additional tests were not required.

The next stage is to output the cart. If the cart has items then you want to displayed them; however. if the cart is empty then you want a message to be shown to the user informing them of this. Your initial solution is to determine which control to render within the view itself. The first attempt at the code looks like this:

<%
       if (count == 0)
           Html.RenderPartial("CartEmpty");
       else
           Html.RenderPartial("DisplayCart", Model.Cart.Items);
   %>

Although that was fairly simple, there is a way to remove the if condition from your view and move it into testable code. The result is that an extension method is created again, which would determine if it should output an empty user control or output the cart. The result is a method which takes in the list together with two action items. One action is what to do when the list is empty; the other is if the list is populated:

<% Html.RenderShoppingCart(Model.Cart.Items, () => Html
.RenderPartial("CartEmpty"), () => Html.RenderPartial("DisplayCart", Model.Cart));
        %>

The tests for your implementation follow the same approach as the tests for the WithDiv implementation. You want to verify that the correct action is being called at the correct point in time based on how many items are in the list:

[Test]
        public void RenderShoppingCart_Renders_Empty_Cart_When_Empty()
        {
            HttpContextBase httpContext = MockRepository.GenerateStub<
HttpContextBase>();
            httpContext.Stub(c => c.Response).Return(MockRepository.GenerateStub<
HttpResponseBase>());

            bool called = false;

            HtmlHelper helper = MockHelper.CreateHtmlHelper(httpContext);
            helper.RenderShoppingCart(new List<ShoppingCartItem>(),
() => called = true, null);

            Assert.IsTrue(called);

}

        [Test]
        public void RenderShoppingCart_Renders_HasData_Action_When_It_Contains_Data()
        {
            HttpContextBase httpContext = MockRepository.GenerateStub<
HttpContextBase>();
            httpContext.Stub(c => c.Response).Return(MockRepository
.GenerateStub<HttpResponseBase>());

            bool called = false;

            HtmlHelper helper = MockHelper.CreateHtmlHelper(httpContext);
            helper.RenderShoppingCart(new List<ShoppingCartItem> {
new ShoppingCartItem() }, null, () => called = true);

            Assert.IsTrue(called);
        }

The result is a very simple and straightforward implementation — one that is more readable than the alternative and is tested:

public static void RenderShoppingCart(this HtmlHelper helper,
IList<ShoppingCartItem> items, Action empty, Action hasData)
        {
            if (items.Count == 0)
                empty();
            else
                hasData();
        }

As for the controls that are actually rendered, the CartEmpty control simply outputs text. The DisplayCart control outputs a table as shown next. The ShoppingCartLine control is rendered for each item in the cart and outputs a row for the table:

<table>
    <tr>
        <td><small><b>Product</b></small></td>
        <td><small><b>Quantity</b></small></td>
        <td><small><b>Price</b></small></td>
        <td></td>
    </tr>
    <%  foreach (ShoppingCartItem item in Model) { %>
        <% Html.RenderPartial("ShoppingCartLine", item); %>
    <%} %>
</table>

Within the ShoppingCartLine control you output the name and the price. You also attach the Quantity property to a textbox. Attaching the property in this way is important for when users want to update the quantity amount, as you will be able to take advantage of the framework itself:

<tr>
        <td><%=Model.Product.Name%></td>

<td><%=Html.TextBox("Quantity", Model.Quantity)%></td>
        <td><%=Model.Product.GetPrice()%></td>
</tr>

With your items now being displayed, the next task is to allow the user to update the quantity. To update the shopping cart item you need some additional logic. First, you need a second Show method that will accept the cartItemId as a parameter to allow you to identify which particular row in the cart you are modifying. The second parameter is the form post data. This will contain any updated values such as the quantity. You can then use this to update your model and your cart.

To simulate this, our tests can creates a FormCollection within the Setup method to provide the result you would expect for the particular form post request; in this case you can simulate the users of the quantity 2 in the form:

formWithQuantityOf2 = new FormCollection();
formWithQuantityOf2.Add("Quantity", "2");

This allows you to simulate how the method will behave when the form is submitted.

Next is the verification that this new method correctly retrieves and saves your cart. You pass in the ID of the item in the shopping cart together with our test form collection:

[Test]
        public void Show_Can_Update_Quantity_Of_Item_In_Shopping_Basket()
        {
            shoppingCart.AddItem(product);

            shoppingCartRepository.Expect(r => r.GetCart(username))
.Return(shoppingCart);
            shoppingCartRepository.Expect(r => r.SaveOrUpdate(shoppingCart))
.Return(shoppingCart);

            ShoppingCartController controller = new ShoppingCartController(
shoppingCartRepository, productRepository,
MockHelper.CreateCredentialsService(username));

            int cartItemId = 0;
            controller.Show(cartItemId, formWithQuantityOf2);

            shoppingCartRepository.VerifyAllExpectations();
        }

You then have a second test to verify the quantity was updated correctly for the correct cart item:

[Test]
        public void Updating_Quantity_Modifies_Item_In_Cart()
        {
            shoppingCart.AddItem(product);

            productRepository.Expect(r => r.Get(PRODUCT_ID)).Return(product);
            shoppingCartRepository.Stub(r => r.GetCart(USERNAME)).
Return(shoppingCart);

shoppingCartRepository.Stub(r => r.SaveOrUpdate(shoppingCart))
.Return(shoppingCart);

            ShoppingCartController controller = new ShoppingCartController(
shoppingCartRepository, productRepository,
MockHelper.CreateCredentialsService(USERNAME));
            int cartItemId = 0;
            controller.Show(cartItemId, formWithQuantityOf2);

            Assert.AreEqual(2, shoppingCart.Items[0].Quantity);
        }

In terms of implementation, you obtain the shopping cart and then the particular shopping cart item based on the ID.

public ActionResult Show(int cartItemId, FormCollection form)
{
    ShoppingCart cart = CreateOrGetCart();
    ShoppingCartItem item = cart.Items.Single(i => i.ID == cartItemId);
    UpdateModel(item, form.ToValueProvider());

    Repository.SaveOrUpdate(cart);

    return RedirectToAction("Show");
}

In the previous method you provided the ID as a parameter. You were able to do this when your ID was a hidden field on the form. As a result it was submitted as a parameter. The updated quantity value was submitted back to the server because you used a form around your input:

<% using (Html.BeginForm()) { %>
        <%= Html.Hidden("cartItemid", Model.ID) %>
        <td><%=Model.Product.Name%></td>
        <td><%=Html.TextBox("Quantity", Model.Quantity)%></td>
        <td><%=Model.Product.GetPrice()%></td>
        <td><%=Html.SubmitButton("Update", "Update", new { id = "submit" })%>
<% } %>

With the ability to update the quantity of your products, you need to change the behavior of your Add To Basket method. If the item already exists then you want to increment the quantity or otherwise add it as a new value. Your test asserts that the number of items in the cart is still one, while the item quantity is in fact 2:

[Test]
        public void If_Item_Already_Exists_In_Basket_Then_Quantity_Is_Incremented_
Instead()
        {
            shoppingCart.AddItem(product);

            stubProductRepository.Expect(r => r.Get(PRODUCT_ID)).Return(product);
            stubShoppingCartRepository.Stub(r => r.GetCart(USERNAME))
.Return(shoppingCart);

stubShoppingCartRepository.Stub(r => r.SaveOrUpdate(shoppingCart))
.Return(shoppingCart);

            ShoppingCartController controller = new
ShoppingCartController(stubShoppingCartRepository,stubProductRepository,
MockHelper.CreateCredentialsService(USERNAME));
            controller.AddToBasket(PRODUCT_ID);

            Assert.AreEqual(1, shoppingCart.Items.Count);
            Assert.AreEqual(2, shoppingCart.Items[0].Quantity);
        }

For the test to pass you modify your logic slightly to see if the cart already contains the item:

if (cart.Contains(product))
    cart.IncrementQuantity(product);
else
    cart.AddItem(product);

The final method is adding the ability to remove items from the cart. Your test follows the same approach as the update test. You first add a product into your cart and then stub your Repository to return this item. After you have called the remove action on your controller, you assert that the cart no longer contains any items:

[Test]
        public void Remove_Should_Remove_Item_From_Shopping_Cart()
        {
            shoppingCart.AddItem(product);

            shoppingCartRepository.Stub(r => r.GetCart(username))
.Return(shoppingCart);
            shoppingCartRepository.Stub(r => r.SaveOrUpdate(shoppingCart))
.Return(shoppingCart);

            ShoppingCartController controller = new ShoppingCartController(
shoppingCartRepository, productRepository, MockHelper.CreateCredentialsService(
username));
            controller.Remove(PRODUCT_ID);

            Assert.AreEqual(0, shoppingCart.Items.Count);
        }

Your implementation simply obtains the cart, removes the item from the collection, and saves the updated item back to your Repository. Your Repository will work the rest out for you:

public ActionResult Remove(int productId)
{
    ShoppingCart cart = CreateOrGetCart();
    cart.RemoveItem(PRODUCT_ID);
    Repository.SaveOrUpdate(cart);
    return RedirectToAction("Show");
}

To execute the action you need a link on your cart page. However, you are already using the form, which means you can't use another Submit button. Instead, you are going to use a hyperlink with a JQuery script attached to the onclick event that will call your action method. In order to keep the UI clean, another helper method should be created to generate your link:

<%=Html.DeleteShoppingCartItemLink(Model)%> </td>

The actual implementation of the link is as follows:

public static string DeleteShoppingCartItemLink(this HtmlHelper html,
ShoppingCartItem item)
        {
            string js = @"$.post(this.href, function(){
                                            window.location.reload();
                                });
                            return false; ";

            return html.ActionLink<ShoppingCartController>(s => s.Remove(item.
Product.ID), "Remove", new { onclick = js, id = "submit" });
        }

Your users can now happily add, update, and remove items from the shopping cart. All your methods have been tested and everything appears to work as expected. Your shopping cart screen is shown in Figure 3-10.

Figure 3-10. Shopping cart

3.4.6. Feature 4: Displaying Addresses

The next stage is to allow the users to select a delivery address. The user will be able to enter a new delivery address if they wish; however, if they have used the site before then you want to provide them with their recently used address to save them from having to enter the address again — in terms of functionality the page is similar to the other three features, yet the implementations are quite different.

To enable this functionality, you need to be able to save address objects into the database. For this to work effectively, you should create another controller, which has the reasonability to handle any address-related functionality. This is to separate the concerns of your system, keeping your responsibilities correct, which improves the readability of your code, but also allowing for the tests to be more focused and readable as a result.

To support the ability for the system to handle addresses, there needs to be an AddressController. This should be capable of ensuring that users can select addresses to use for delivery. After a user has selected an address, it will need to be saved into the database for future use. The following test will verify that the Select method can accept an address object, and that it will correctly call into the Repository, which will handle the saving of the object:

[SetUp]
        public void Setup()
        {
            address = new Address
                        {
                            StreetAddress1 = "Test1",
                            StreetAddress2 = "Test2",
                            City = "City",
                            State = "State",
                            PostCode = 123
                        };
        }

        [Test]
        public void Address_Can_Save_Address_To_Database()
        {
            IAddressRepository repository = MockRepository.GenerateMock<
IAddressRepository>();
            repository.Expect(r => r.SaveOrUpdate(address)).Return(address);

            AddressController controller = new AddressController(
repository, MockHelper.CreateCredentialsService(USERNAME));
            controller.Select(address);

            repository.VerifyAllExpectations();
        }

The following test then verifies that after a user has selected an address they are redirected to the summary page:

[Test]
        public void After_Adding_Address_Should_Redirect_To_Summary()
        {

IAddressRepository repository = MockRepository.GenerateStub<
IAddressRepository>();
            repository.Expect(r => r.SaveOrUpdate(address)).Return(address);

            AddressController controller = new AddressController(
repository, MockHelper.CreateCredentialsService(USERNAME));
            RedirectToRouteResult result = controller.Select(address) as
RedirectToRouteResult;

            Assert.AreEqual("Summary", result.RouteValues["action"]);
            Assert.AreEqual("Checkout", result.RouteValues["controller"]);
        }

Based on your database schema you also need to attach the current UserID to the address before it can be saved. By extending your Credentials service you can return the current UserID from the user who is logged in. This is provided by the ASP.NET membership provider; we will go into more detail in Chapter 4. In your test, you can first set your UserID on the object to be empty — this is to ensure you are testing against a known value. In your assertion, simply verify that the value of the object is as you expect. Lever stub objects make testing your system easier:

[Test]
        public void When_Saving_Address_It_Gets_UserID_To_Attach_To_Address()
        {
            Guid userId = Guid.NewGuid();
            address.UserId = Guid.Empty;

            IAddressRepository repository = MockRepository.GenerateStub<
IAddressRepository>();
            repository.Stub(r => r.SaveOrUpdate(address)).Return(address);

            ICredentialsService credentialsService = MockRepository.GenerateStub<
ICredentialsService>();
            credentialsService.Stub(i => i.GetUsername()).Return(USERNAME);
            credentialsService.Stub(i => i.GetUserID()).Return(userId);

            AddressController controller = new AddressController(
repository, MockRepository.GenerateStub<ICacheService>(), credentialsService);
            controller.Select(address);
            Assert.AreEqual(userId, address.UserId);
        }

The final stage is to allow users to actually enter their address and then construct your Address object. In the Address/Select view, you will have a header and then render your partial control:

<h3>New Address</h3>
<% Html.RenderPartial("NewAddress"); %>

The NewAddress control renders a fieldset collection. Each textbox has the same name as the property on your address object:

<fieldset class="address-form">
    <legend>Enter your Address</legend>
    <ol>

<li>
            <label>Street Address 1</label>
            <%=Html.TextBox("StreetAddress1")%>
        </li>
        <li>
            <label>Street Address 2</label>
            <%=Html.TextBox("StreetAddress2")%>
        </li>
        <li>
            <label>City</label>
            <%=Html.TextBox("City")%>
        </li>
        <li>
            <label>State</label>
            <%=Html.TextBox("State")%>
        </li>
        <li>
            <label>Post Code</label>
            <%=Html.TextBox("PostCode")%>
        </li>
    </ol>
</fieldset>

When the form is submitted, it goes to the Select method you tested previously. Because you use the fieldset with the correctly named input fields, your Address object is automatically constructed and populated for you. The result is that the implementation of the action method can be as follows:

public ActionResult Select(Address address)
{
    address.UserId = Credentials.GetUserID();
    Repository.SaveOrUpdate(address);

    return RedirectToAction("Summary", "Checkout");
}

With the ability to add new addresses into the database for a particular user, the next feature you need to implement is the ability to display existing addresses. This allows users to select a previously entered address instead of having to enter the same address each time.

For this to work effectively, a user should be able to select an address when he visits a page, and it should also have a list of his existing addresses. To have this information you need to return it as part of your view model page.

[Test]
        public void Select_returns_addresses_for_customer_attached_to_model()
        {
            Guid userId = Guid.NewGuid();

            IAddressRepository repository = MockRepository.GenerateStub<
IAddressRepository>();
            repository.Stub(r => r.GetAllAddressForCustomer(userId)).Return(
new List<Address> {address});

            ICredentialsService credentialsService = MockRepository.GenerateStub<
ICredentialsService>();

credentialsService.Stub(c => c.GetUserID()).Return(userId);

            AddressController controller = new AddressController(repository,
MockRepository.GenerateStub<ICacheService>(), credentialsService);
            AddressSelectorModel addressModel = controller.Select().GetModel<
AddressSelectorModel>();

            Assert.IsTrue(addressModel.Addresses.Contains(address));
        }

After you have the addresses on your model, you can output the information on the page. For each address returned, create a new radio button that is assigned the address ID as the value with the address text next to it. With this wrap it in a form, when the form is submitted the SelectExisting action will be called on your Address controller.

<% using (Html.BeginForm("SelectExisting", "Address")) { %>
    <% foreach (Address a in Model.Addresses) {%>
            <%=Html.RadioButton("addressId", a.ID)%>
            <%= Html.Encode(a.GetAddressText()) %> <br />
    <% } %>

    <%=Html.SubmitButton("Proceed", "Use this address", new { id = "submit"})%>
<% } %>

If the user has previously entered an address, then this will be selectable on the UI, as shown in Figure 3-11.

Figure 3-11. Previous address is selectable

With the form sending the request, the next stage is to implement the SelectExisting method. The test for this method is shown next; you need to mock the IAddressRepository and state that you expect a call to the FindAddressByUserIdAndAddressId method. This is what will be called in order for the method to identify the Address object based on the ID provided by the form:

[Test]
        public void SelectExisting_Address_Pulls_It_From_Repository()
        {
            Guid userId = Guid.NewGuid();
            IAddressRepository addressRepository = MockRepository.GenerateMock<
IAddressRepository>();
            addressRepository.Expect(r => r.FindAddressByUserIdAndAddressId(
userId, 1)).Return(address);

            ICredentialsService credentialsService = MockRepository.GenerateStub<
ICredentialsService>();
            credentialsService.Stub(c => c.GetUserID()).Return(userId);

            AddressController controller = new AddressController(
addressRepository, MockRepository.GenerateStub<ICacheService>(),
credentialsService);

            int addressId = 1;
            controller.SelectExisting(addressId);

            addressRepository.VerifyAllExpectations();
        }

Your implementation then calls your method:

[AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SelectExisting(int addressId)
        {
            Address address = Repository.FindAddressByUserIdAndAddressId(
Credentials.GetUserID(), addressId);

            return RedirectToAction("Summary", "Checkout");
        }

To allow your checkout controller to access this information you need a way to store the object. There are multiple ways to handle this; in this example, you're going to use System.Web.Caching.Cache that is a builtin part of the framework. The cache object is accessible via HttpContext.Current, which is a singleton for your current http request. By adding an object to the cache the object will be available across multiple requests. This means you can temporarily store your address to access later in the process. The implementation of the cache is very similar to the implementation of the credentials service (which will be discussed in Chapter 4), as they both reply on the core ASP.NET Framework and external entities. For now, you will take advantage of being able to stub the interface shown next:

public interface ICacheService
{
    void Add(string cacheID, object cache);
    object Get(string cacheID);
}

To verify objects are being added to the cache correctly you can use a mock object. The two tests for new and existing addresses are as follows:

[Test]
        public void New_Address_Is_Added_To_The_Cache_For_The_User()
        {
            IAddressRepository repository = MockRepository.GenerateStub<
IAddressRepository>();
            repository.Stub(r => r.SaveOrUpdate(address)).Return(address);

            ICacheService cache = MockRepository.GenerateMock<ICacheService>();
            cache.Expect(r => r.Add(USERNAME + "ShippingAddress", address));

            AddressController controller = new AddressController(repository, cache,
MockHelper.CreateCredentialsService(USERNAME));
            controller.Select(address);

            cache.VerifyAllExpectations();
        }

        [Test]
        public void SelectExisting_Adds_Address_To_Cache()
        {
            IAddressRepository repository = MockRepository.GenerateStub<
IAddressRepository>();
            repository.Stub(r => r.FindAddressByUserIdAndAddressId(Guid.Empty, 0))
.IgnoreArguments().Return(address);

            ICacheService cache = MockRepository.GenerateMock<ICacheService>();
            cache.Expect(r => r.Add(USERNAME + "ShippingAddress", address));

            AddressController controller = new AddressController(repository, cache,
MockHelper.CreateCredentialsService(USERNAME));
            int addressId = 1;
            controller.SelectExisting(addressId);

            cache.VerifyAllExpectations();
        }

With these tests passing, you can be confident that the object will be stored correctly in your cache for later use. The implementing code required is next:

Cache.Add(Credentials.GetUsername() + shippingAddresskey, address);

With your cache in place, the final task is to display a summary screen together with a confirmation screen to confirm that the order has been successful.

3.4.7. Feature 5: Displaying Confirmation

By now you should see a very common theme with unit testingTDD. Outline your expectations for a targeted feature or problem then write the implementing code. By having your controller testable and your dependencies injectable, you have control over what you expect to happen. The final feature is to show the confirmation screen. This was implemented following a similar pattern to previous features. After the user has entered their address they will see the confirmation page, as shown in Figure 3-12.

Figure 3-12. Confirmation screen

To see the final implementation please refer to the sample project.

3.4.8. Applying Unit Tests to Legacy ASP.NET WebForms Code

In this chapter we have covered how to write tests for both ASP.NET WebForms and ASP.NET MVC as you are designing and developing the system. However, if you already have an ASP.NET WebForms application you might not have unit tests already in place. Working with legacy code is a very common problem and could be an entire book, in fact it is as Michael Feathers wrote Working Effectively with Legacy Code and is a highly recommended read. But before you head off and read that book, we wanted to provide you with some initial considerations about how you can add unit tests to an existing ASP.NET application that hasn't been developed with testability in mind.

When you start writing unit tests for legacy code you will face some initial issues. You find yourself in a catch-22 position where you want to add tests to ensure the code works correctly; however, you will generally need to change (or refactor) the code in order to make this happen — or at least you will if you want useful, non-fragile tests. In order to mitigate the risk of changing the code and not breaking anything there are a few techniques to try. Firstly, there are many refactoring tools available to support this type of activity for ASP.NET based applications. Two of the popular tools are JetBrains ReSharper (http://www.jetbrains.com/resharper/index.html) and DevExpress Refactor! (www.devexpress.com/Products/Visual_Studio_Add-in/Refactoring/). These tools can take blocks of code and extract them into different classes and methods, adding parameters as required. By using a tool you can eliminate the chance of making a simple mistake and perform the change in a much easier fashion. However, even when using a tool you still have the possibility of breaking some functionality while attempting to move your code into a testable state.

One approach to take is to write higher level tests covering the part of the functionality that you plan to refactor in order to add unit tests. You want the tests to cover the existing functionality so that when you refactor the code you can re-run the tests to ensure that the functionality is still in place. Ideally, you want the tests to be as close and targeted as possible, and because parts of the system haven't been refactored yet, the tests will be integration tests (discussed in Chapter 4). Sometimes this isn't possible due to a too tightly coupled dependency, in which case you should look at even higher level tests such as UI testing (Chapter 5) and acceptance testing (Chapter 6) to provide you with an initial safety net during the refactoring stages. After you have written the tests and made the code change, you still have the tests in place to support and continue the development of the application.

Once you have the tests covering the functionality you can start taking steps to improve the code. You should then write unit tests in a similar way to how you would with TDD in order to define how you want your architecture to be and how you want to interact with the system. This will give you something to aim for when refactoring, while also allowing you to remain focused and know if you are finished with the refactoring stage. Once this new unit test is passing, you can re-run your higher-level tests to ensure the other affected parts of the system still work as desired. If you continue this process, then you should start to build up a collection of acceptance tests around your application.

However, you need to ask yourself a question — why are you adding the test cases? Retrofitting test cases is a costly process, especially when you need to refactor the code to support it. As such, you need to be clear about the advantages you want to add to the code by taking the effort to write the your tests.

If you want to ensure you don't cause any regressions, then you are better looking at techniques such as acceptance testing (discussed in Chapter 6) that allow you to add automated tests without having to refactor large parts of the application. If your aim is to support adding new functionality and improve maintenance of the system, then it is worth making the effort to write the tests and improve areas of your code as you're working on. However, if it's just to say you have unit tests or that you have 70 percent test coverage, then you should ask if it is worth the effort to retrofit these tests. Instead, it might make more sense to put your time and effort into refactoring the code as we have described only when you actually need to change the code instead of spending three months attempting to add the tests. It will mean you don't have as much coverage straight away, but it will allow you to target your time and efforts more effectively.

3.4.9. Summary

This chapter covered how to start unit testing and writing code using Test Driven Development. By expressing your expectations ahead of time you can ensure that your code meets them after you have implemented the features. After you change the code and add new features, you can use the tests to verify that the application is still working as you expect. The most important item to remember is how to keep everything separated, isolated, and think about how you are going to test the system and write the test before you write any code to ensure that the first two items are achieved.

By stubbing and mocking your dependencies, you can be confident that your controllers are working as expected. Chapter 4 will cover how you implement the layer underneath. Chapter 5 will cover the UI layer.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.250.11