I was relatively new to Unit Testing before couple of years but have horned my skills in unit testing since then. Before that, I (and my team members) always complained ad-hoc nature of the business and time constraint factor for not writing unit tests. Though I agree it was the factor most of the time, but it also came down to us not being strict in writing tests and getting better code coverage. Unless the code hasn't got proper test coverage, code is always suspect to errors during future changes.
Recently, working with 3rd party components, came across few scenario's which was comparatively tough and time consuming operation to test. When doing unit testing, one always comes to a point where there this “kind of hard” part to test since the part depends on something you might not have control over or depends on the functionality of the dependency to complete.
In self written code, I usually prefer laying down strict contract for the components via Interfaces, pass it in the constructor (constructor injection) and mock using Mocking framework (I prefer Moq) and hence, no big issue while writing unit tests.
But consider scenarios when you don’t have access to component or there will not be a setter for property on the object (3rd party component object) for some reason (probably security).
In above scenario, Extract and Override pattern for Unit Testing comes handy.
I will try explaining it using my favourite HybridCar class example. I would recommend you have a look at Dependency Injection explained article.
public interface IFuel
{
string UnitOfMeasurement { get; set; } //litres, gallon etc..
decimal PricePerUnit { get; set; }
string CalculateMileage();
}
public class Petrol : IFuel
{
private string _unitOfMeasurement;
private decimal _pricePerUnit;
#region IFuel Members
public string UnitOfMeasurement
{
get { return "Litre"; }
set { _unitOfMeasurement = value; }
}
public decimal PricePerUnit
{
get { return 1.30M; }
set { _pricePerUnit = value; }
}
public string CalculateMileage()
{
return "While driving in city, using Petrol as a Fuel gives 10km mileage";
}
#endregion
}
public class HybridCar
{
private StartValidator _validator
private IFuel _fuel;
public HybridCar(IFuel fuel)
{
_fuel = fuel;
}
public string Drive()
{
return _fuel.CalculateMileage();
}
public bool Start()
{
if(_validator.IsValid())
return true;
return false;
}
}
Consider, StartValidator is the class which is not mockable or it's a legacy code where performing refactoring and extracting interface would be a big job. For us to test Start method, we have a dependency that calls and checks if the condition is valid for the HybridCar to start, this basically makes it pretty hard to test, unless we refactor our code and user interface IStartValidator, pass it in the constructor and mock StartValidator using moq or hand write the stub class for it. But as I mentioned before, consider we don't have access to the StartValidator class.
This sort of scenarios can be one of the reason where people don't write test for the code and the code coverage falls over. But there is a way to test and it is quite simple. The way to do it is actually extracting the dependency and test the Valid functionality. Since with us, we don't really care about the implementation detail for IsValid, as we want to test the Start functionality to see if it's valid to start. Let's see how to do it.
public class HybridCar
{
private StartValidator _validator
private IFuel _fuel;
public HybridCar(IFuel fuel)
{
_fuel = fuel;
}
public string Drive()
{
return _fuel.CalculateMileage();
}
public bool Start()
{
if(IsValid())
return true;
return false;
}
protected virtual bool IsValid()
{
return _validator.IsValid();
}
}
We added a virtual method called IsValid so that we can override it when we create a stub for it. Now for our stub, we simply override the IsValid method so that it always returns true (or change it based on your test cases).
public class HybridCarStub : HybridCar
{
public bool Valid = true;
protected override bool IsValid()
{
return true;
}
}
And finally in our unit test, we can write something like this
[Test]
public void Start_IsValid_ReturnsTrue()
{
//Arrange-------
HybridCar car = new HybridCarStub();
car.Valid = true;
//Act-----------
bool result = car.Start();
//Assert--------
Assert.IsTrue(result);
}
[Test]
public void Start_IsNotValid_ReturnsFalse()
{
//Arrange-------
HybridCar car = new HybridCarStub();
car.Valid = false;
//Act-----------
bool result = car.Start();
//Assert--------
Assert.IsFalse(result);
}
Usually while writing tests, I tend to follow a AAA pattern (Arrange-Act-Assert), which helps in seperating the logical content of tests. It also helps someone else to go through the test code quickly. There are definitely better ways to lay your architecture to suit testing requirements but in certain scenarios, extract and override pattern for unit testing out ways the amount of effort required to refactor the code to make it unit testable.