I have seen companies where unit testing is a theory than practice. Some think that creating a unit testing project in Visual Studio is unit testing.
What is unit testing then? Like a building constructed brick by brick, software is built with classes. Similar to faulty bricks can cause damage to the structure of the building, a badly written class can harm the application code.
I started my career writing bad code, and improved my coding style with constant learning under great Teachers. I know what is a bad code because I have written lot of it
So how do we write testable code?
Lets take a simple example of layered architecture which is very much prevalent in the industry. A three layer architecture will have Data Access Layer (DAL), Business Layer (BL) and Presentation Layer (PL).
So sample code looks like as shown below.
class Program
{
static void Main(string[] args)
{
PresentationLayer presentationLayer = new PresentationLayer();
presentationLayer.Call();
}
}
class PresentationLayer
{
BusinessLayer _businessLayer = new BusinessLayer();
public void Call()
{
Console.WriteLine("Presentation Layer Called");
_businessLayer.Call();
}
}
class BusinessLayer
{
DataAccessLayer _dataAccessLayer = new DataAccessLayer();
public void Call()
{
Console.WriteLine("Business Later Called");
_dataAccessLayer.Call();
}
}
class DataAccessLayer
{
public void Call()
{
Console.WriteLine("Data Access Layer Called");
}
}
Presentation layer makes a call to business logic layer, which in turn calls data access layer. Now unit testing means we should be able to test single functionality of one class. Can we test the call in business layer without having reference to data access layer? To make matter worse data access layer will mostly be written tightly coupled with database. So you can not test business layer until you have the data access layer and database.
Still this is a not a convincing answer for having unit test? Then answer to question “how do you test all business scenarios around the BL?” could be more reasonable
Without unit test, business scenarios will be lost under the pile of code. And no one in the team can be sure that they did not break the component they touched.
To make the component testable one of the technique is to use Dependency Inversion Principle. With dependency inversion principle, we are going to compose the class as shown below.
class Program
{
static void Main(string[] args)
{
IDataAccessLayer dataAccessLayer = new DataAccessLayer();
IBusinessLayer businessLayer = new BusinessLayer(dataAccessLayer);
//We are composing the object
PresentationLayer presentationLayer = new PresentationLayer(businessLayer);
presentationLayer.Call();
}
}
class PresentationLayer
{
IBusinessLayer _businessLayer ;
public PresentationLayer(IBusinessLayer businessLayer)
{
_businessLayer = businessLayer;
}
public void Call()
{
Console.WriteLine("Presentation Layer Called");
_businessLayer.Call();
}
}
interface IBusinessLayer
{
void Call();
}
class BusinessLayer : IBusinessLayer
{
IDataAccessLayer _dataAccessLayer;
public BusinessLayer(IDataAccessLayer dataAccessLayer)
{
_dataAccessLayer = dataAccessLayer;
}
public void Call()
{
Console.WriteLine("Business Layer Called");
_dataAccessLayer.Call();
}
}
interface IDataAccessLayer
{
void Call();
}
class DataAccessLayer : IDataAccessLayer
{
public void Call()
{
Console.WriteLine("Data Access Layer Called");
}
}
Our sample unit test around business layer with a stub data access layer is as shown below.
[TestClass]
public class UnitTest1
{
public class DataAccessStub : IDataAccessLayer
{
public void Call()
{
Console.WriteLine("Data access stub called");
}
}
[TestMethod]
public void TestCall()
{
IDataAccessLayer dataAccessLayer = new DataAccessStub();
IBusinessLayer businessLayer = new BusinessLayer(dataAccessLayer);
businessLayer.Call();
}
}
Instead of using database dependent data access layer, we are using DataAccessLayerStub. We can now test all business scenarios around the business layer with the help dependency inversion principle.
I will explain more about stub in my next post. So keep watching