Friday, June 27, 2008

Writing Testable Code - Part I

In the current project that I am working on we decided that we will strive to write as many unit tests as possible. Here I will try to share some lessons learned from this experience.

The application was broken down to following layers, A DAL that communicates with the underlying database, a service layer that implements business rules and the UI layer.

We started with writing the DAL and some services. Since our services didn't have any state we decided to go with static classes. A typical service class might look like this.

public static class OrderService
{
public static void ProcessOrder(int orderId)
{
OrderHeaderDAL headerDAL = new OrderHeaderDAL();
OrderDetailDAL detailDAL = new OrderDetailDAL();
CustomerDAL customerDAL = new CustomerDAL();

//Do the processing.

}
}


We managed to write unit tests for the DAL without any issues. But as soon as we wanted to write unit it was apparent that we cannot do this because the service classes are directly coupled to the DAL. Clearly we needed to decouple the Services from the DAL and the first solution that came to my mind was dependency injection. To do this we needed to make the following changes




  • Make the service class methods instance based rather than static


  • Define a set of interfaces that will decouple the DAL from services


  • Add a factory class that will assemble the service classes


service classes instance based rather than static and add a layer of DAL interfaces that the services will depend on instead of the concrete classes . Now the above example will look like this.



public class OrderService
{
public IOrderHeaderDAL OrderHeaderDal
{
get;
set;
}

public IOrderDetailDAL OrderDetailDal
{
get;
set;
}

public ICustomerDAL CustomerDal
{
get;
set;
}

public void ProcessOrder(int orderId)
{

//use the injected DAL's
CustomerDal.DoWhatEver();
}

//Whenver you want to use the order service you call the ServiceFactory
OrderService service = ServiceFactory.CreateOrderService();


This solution worked. now we can mock the DAL and write unit tests for the service classes easily. But this had the following issues. Some methods in a service don't use all the DAL classes that the service depends on. But when the service factory creates the service it injects all dependant objects regardless of weather they are used or not. In the next post I will describe how I fixed those issues.

2 comments:

Madhawa said...

Good topic mate.

Couple of years ago I used this technique to create a generic shopping cart which can plug into many e-commerce applications. And at that time I didn’t know I was using dependency injection in a manual way.  After that I tried to use couple of framework like Castle project, spring.net etc… But never had a chance to use those in real world applications. BTW now Microsoft has released their own DI (aka IOC) framework called Unity. It’s seems like an extension to their object builder which exist for some time in application blocks.

I totally agree with you on static class issue. Even though static classes are making our lives easy it’s a really good practice to write instance classes over static or singleton classes since it will be more testable.

Now there are some tools which help us to detect singletons (static classes also categorize as singletons) in our source codes. Google has that kinda tool called Google singleton detector for java and I don’t know whether there are any for .net.

Waiting for your second part of the post buddy.

jayalal said...

One more nice thing with dependency injection, Is ability to use mock object while Unit testing.In java there are libraries like Jmock are available so that U can easily simulate and Inject any complex object while unit testing.