in

Chennai .Net User Group

A platform that enables you to Learn, Share & Grow (India's first .Net user group)

Shiju Varghese's Blog

July 2009 - Posts

  • ASP.NET MVC 2 Preview 1 Released

     Microsoft has released Preview 1 version of ASP.NET MVC 2. You can download  ASP.NET MVC 2 Preview 1 from here.  The new features are Templated Helpers, Areas and Support for Data Annotations. For more details visit the following links

    ScottGu on ASP.NET MVC V2 Preview 1 Released 

    Phil Haack on ASP.NET MVC 2 Preview 1 Released

    Walkthrough: Using Templated Helpers to Display Data

     Walkthrough: Organizing an ASP.NET MVC Application by Logical Areas

    How to: Validate Model Data Using DataAnnotations Attributes

  • Introduction to Test-Driven Development with ASP.NET MVC

    One of the greatest advantages of ASP.NET MVC is the support of testability, which enables to develop Test-Driven Development (TDD) in an easy manner. A testable application should be developed in a loosely coupled manner so that you can test the independent parts of the application. For developing testable applications, the support of developer frameworks is very important and the frameworks should be designed to facilitate building testable applications. One of the design goals of ASP.NET MVC was testability so that you can easily develop testable application with the ASP.NET MVC framework. In this post, I will give an introduction to Test-Driven Development (TDD) with ASP.NET MVC using NUnit unit test framework.

    Introduction to Test-Driven Development

    TDD is a design approach that follows a Test First development where you write a test before you write just enough production code to fulfill that test and refactoring. The TDD model development is also known as Red-Green-Refactor style development.

    The following are the workflow of TDD

    1. Requirement identified

    2. Write an automated test

    3. Run tests and make sure new one FAILS (RED)

    4. Write some code

    5. Run tests to make sure all PASS (GREEN)

    6. Refactor

    7. Repeat

    In this example, I will explain a scenario where users can view list of categories and also able to add new category into the application. The following are the behaviors of our simple reference application

    1. Users should be able to view list of Categories

    2. The category list should support paging

    3. The Category Name should be mandatory while creating a new Category

     

    Code listings of the application

    Category model

    public class Category {
    public int CategoryID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    }

    ICategoryRepository

    public interface ICategoryRepository {
    IQueryable<Category> GetCategories();
    void Save(Category category);
    void Delete(int id);
    Category Read(int id);
    }

    ICategoryService

    public interface ICategoryService {
    IQueryable<Category> GetCategories();
    void Save(Category category);
    Category Read(int id);
    void Delete(int id);
    }

     

    CategoryController - List Action

    public ActionResult List(int? page)
    {
    return View();
    }

    Currently the List action method does not contain any implmentation logic. We will write the implementation code after writing a failure test.

    Unit Tests

    In TDD, we start with writing a failure test. In this post, I am using NUnit for unit test. You can download NUnit from http://NUnit.org. If you want a NUnit test template for ASP.NET MVC, check the blog post Updated NUnit Templates for ASP.Net MVC 1.0 RTM .

    The below is the test for the behaviours of the category list

    [TestFixture]
    class
    CategoryControllerTest
    {
    Mock<ICategoryRepository> _repository;
    ICategoryService _service;
      [SetUp]
    public void Setup()
    {
    _repository = new Mock<ICategoryRepository>();
    _service = new CategoryService(_repository.Object);
    }
    [Test]
    public void List()
    {
    IQueryable<Category> fakeCategories = new List<Category> {
    new Category { Name = "Test1", Description="Test1Desc"},
    new Category { Name = "Test2", Description="Test2Desc"},
    new Category { Name = "Test3", Description="Test3Desc"}
    }.AsQueryable();

    _repository.Setup(x => x.GetCategories()).Returns(fakeCategories);
    CategoryController controller = new CategoryController(_service);
    // Act
    ViewResult result = controller.List(null) as ViewResult;
    // Assert
    Assert.IsNotNull(result, "View Result is null");
    Assert.IsInstanceOf(typeof(PagedList<Category>),
     result.ViewData.Model, "Wrong ViewModel");
    var categories = result.ViewData.Model as PagedList<Category>;
    Assert.AreEqual(3, categories.Count,
    "Got wrong number of Categories");
    Assert.AreEqual(0, (int)categories.PageIndex,
    "Wrong page Index");
    Assert.AreEqual(1, (int)categories.PageNumber,
    "Wrong page Number");
    }
     

    The Unit Test class decorated with TextFixure attribute which specify that it is unit test class. The test attribute is an indication that it is a test method. The method with Setup attribute will call before execute every test method. This method is using for initialization purpose. If you have five test methods, it will call five times. In the above test, I have used mock objects. Mock objects are simulated objects that can mimic the behaviour of real objects. This is very useful when real object is impractical to incorporate into a unit test such as you don't want to hit the database. In this case, I don't want to hit the database. Instead, I created three fake category objects and setup that returns this fake category objects when there is a call for GetCategories method of the Categoryrepository object.

    _repository.Setup(x => x.GetCategories()).Returns(fakeCategories);

    The Mock<ICategoryRepository> contains the methods for the behaviour of Mock repository and the repository.Object reperesent the actual repository object. For mocking, I am using the Moq framework. You can download Moq framework from http://code.google.com/p/moq.

    The Assert class is using for verfying the results. The test verify the following behaviour with the three fake category objects

    1. The ViewResult should not be null.
    2. The ViewResult should be an instance of PagedList<Category> that supports paging.
    3. The category count should be 3.
    4. The page index should be 0 and page number should be 1.

    When running the unit test, it will fail becuase we have not written any code for List Action method.

    The below shows fail status (Red Signal) from NUnit GUI test runner.

     

     

    In the next step (Green stage), we have to write the code to pass the test. The below is the List action method written for pass the test.

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult List(int? page)
    {
    int pageSize = Convert.ToInt32(
    ConfigurationManager.AppSettings["pagesize"]);
    var categories = _categoryService.GetCategories().
    ToPagedList<Category>(page ?? 0, pageSize);
    return View(categories);
    }

    When running the test again, it will pass becuase we have written necessary code to pass the test. In the last stage of TDD is refactor where you will be writing code to improve the overall architcture of the application. In this stage, you can write code confidently because your code is covered by unit tests.

    In the next step, you will be writing more unit tests for new identified requirements and behaviours. The below unit test is for the following behaviours while creating a new category.

    1. The category name should be required. If name is empty, an error message should be set into model state.

    2. After creating a new category, it would be redirect to List action method.

    [Test]
    public void Category_New()
    {
    // Arrange
    CategoryController controller = new CategoryController(_service);
    var category = new
    Category
    { Name = "Test", Description = "TestDescription" };
    // Act
    var result = (RedirectToRouteResult)controller.Save(category);
    // Assert
    Assert.AreEqual("List", result.RouteValues["action"]);
    }
    [Test]
    public void Category_Name_Required()
    {
    // Arrange
    CategoryController controller = new CategoryController(_service);
    // Act
    Category category = new Category();
    category.Name = String.Empty;
    var result = (ViewResult)controller.Save(category);
    // Assert
    var error = result.ViewData.ModelState["Name"].Errors[0];
    Assert.AreEqual("Name is required.", error.ErrorMessage);
    }

    The below is the implementation code for the above tests.

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Save(Category category)
    {
    //Validations
    EnsureValidations(category);
    if(!ModelState.IsValid)
    {
    return View("SaveCategory");
    }
    _categoryService.Save(category);
    return RedirectToAction("List");
    }
    private void EnsureValidations(Category category)
    {
    if (string.IsNullOrEmpty(category.Name))
    {
    ModelState.AddModelError("Name", "Name is required.");
    }
    }
     

    The below shows success status (Green Signal) from NUnit GUI test runner.

     
     

    Applying Dependency Injection

    In this application, I am using Dependency Injection pattern that making the application more loosely coupled and it improves the testability of the application. If you are not familiar with Dependency Injection and Inversion of Control (IoC), I recommend to read Martin Fowler’s article Inversion of Control Containers and the Dependency Injection pattern.  Please check my blog post ASP.NET MVC Tip: Dependency Injection with Unity Application Block that demonstrated how you can use the Unity Application Block to perform Dependency Injection within an ASP.NET MVC application.

    public static void ConfigureUnityContainer() {
    IUnityContainer container = new UnityContainer();
    // Registrations
    container.RegisterType<DBData , DBData>
    (new HttpContextLifetimeManager<DBData>());
    container.RegisterType<ICategoryRepository, CategoryRepository>
    (new HttpContextLifetimeManager<ICategoryRepository>());
    container.RegisterType<ICategoryService, CategoryService>
    (new HttpContextLifetimeManager<ICategoryService>());
    ControllerBuilder.Current.SetControllerFactory(
    new UnityControllerFactory(container));
    }

    The above code setup the depencies with Unity Application block and configure the controller factory with Unity.

    Summary

    In this post, I demonstrated how to build Test-Driven Development (TDD)  applications with Microsoft ASP.NET MVC. ASP.NET MVC is an excellent framework for building TDD based  applications with highly loosely coupled manner.

    You can download the source code  from here.

  • T4 Template for generate Table Script from XSD

    The below T4 template will generate Create Table script from a XSD file. The Template will create a dataset from a XSD file and generate create table script from the dataset.

     

        1 <#@ template language="C#v3.5" hostspecific="True" debug="True" #>

        2 <#@ assembly name="System.Core" #>

        3 <#@ assembly name="System.Data" #>

        4 <#@ assembly name="System.Xml" #>

        5 <#@ output extension=".sql" #>

        6 <#@ import namespace="System" #>

        7 <#@ import namespace="System.IO" #>

        8 <#@ import namespace="System.Xml" #>

        9 <#@ import namespace="System.Data" #>

       10 <#PrepareToRender(); #>

       11 <#

       12 foreach (DataTable dt in ds.Tables) {

       13     tableName= dt.ToString();

       14 #>   

       15 CREATE TABLE <#= tableName #>

       16 (

       17 <#

       18 PushIndent("  ");

       19 foreach (DataColumn dc in dt.Columns) {

       20 WriteLine( dc.ToString() + "  " + MapToSqlType(dc.DataType.Name) + ",");

       21  }

       22  PopIndent();

       23 #>

       24 )

       25 <#

       26 }

       27 #>

       28 <#+

       29 DataSet ds;

       30 string tableName;

       31 void PrepareToRender()

       32 {

       33 ds = new System.Data.DataSet();

       34 //Load the XSD

       35 ds.ReadXmlSchema("Metadata.xsd");

       36 }

       37 string MapToSqlType(string clrType)

       38 {

       39   switch(clrType)

       40   {

       41   case "String":

       42   return "Varchar(50)";  

       43   case "Int32":

       44   return "int";

       45   //Do other mapings

       46   default: 

       47   return clrType;

       48   }

       49 }

       50 #>

     

     


Copyright © 2002-2008 Chennai .Net User Group. All Rights Reserved. Microsoft and Microsoft logo's are trademarks of Microsoft Corporation