I am not sure I understand why do you want to do this (apart from dealing with an intellectual challenge). This kind of code, where you work directly with some system level API, is very hard to unit test, TDD style or not, and to be frank, I don't find it very valuable to try it in a real project.
Most of the task you describe is calling the right low level API method with the right parameter. And the rest of the code as is may be so trivial, it wouldn't necessarily warrant the introduction of a dedicated interface, mock objects etc. I would be content having an integration test to verify on a higher level that the whole stuff works. But this is just my 2 cents.
Unit testing for me is not about following rulebooks or strict definitions. In real life, I don't really care whether my tests are "real" unit tests or not; as long as my code is being covered by automated and repeatable tests, I am fine. I prefer the pragmatic approach.
You mention two books in which one of the primary messages is "The Boy Scout Rule" i.e. clean up the code as you touch it. If you have a working system, a massive rewrite is counter-productive. Instead, as you add new functionality, make sure you improve the code as it stands.
- Write unit tests to cover the existing code that you need to change.
- Refactor that code so it is more pliable for change (making sure your tests still pass).
- Write tests for the new/revised functionality
- Write code to make the new tests pass
- Refactor as necessary.
To dive further in, Feathers talks about testing the application at its seams: the logical points at which the units connect. You can take advantage of a seam to create a stub or a mock for a dependency so that you can write tests around the dependent object. Let's take your AddressBO as an example
public class AddressBO
{
public TransferObject GetAddress(string addressID)
{
if (StringUtils.IsNull(addressID))
{
throw new ValidationException("Address ID must be entered");
}
AddressDAO addressDAO = new AddressDAO();
return addressDAO.GetAddress(addressID);
}
}
There is an obvious seam between the AddressBO and the AddressDAO. Let's create an interface for the AddressDAO and allow the dependency to be injected into the AddressBO.
public interface IAddressDAO
{
TransferObject GetAddress(addressID);
//add other interface methods here.
}
public class AddressDAO:GenericDAO, IAddressDAO
{
public TransferObject GetAddress(string addressID)
{
///implementation goes here
}
}
Now you doctor up your AddressBO to allow for injection
public class AddressBO
{
private IAddressDAO _addressDAO;
public AddressBO()
{
_addressDAO = new AddressDAO();
}
public AddressBO(IAddressDAO addressDAO)
{
_addressDAO = addressDAO;
}
public TransferObject GetAddress(string addressID)
{
if (StringUtils.IsNull(addressID))
{
throw new ValidationException("Address ID must be entered");
}
//call the injected AddressDAO
return _addressDAO.GetAddress(addressID);
}
}
Here we're using "poor man's dependency injection." Our only goal is to break the seam and allow us to test the AddressBO. Now in our unit tests we can make a mock IAddressDAO and validate the interactions between the two objects.
Best Answer
MSDN has some advice on Type naming.
I also recommend reading Framework Design Guidelines book for a more detailed discussion on naming and lots of extra design advice.