views:

67

answers:

2

I am a TDD newb and I would like to figure out how to test the following code.

I am trying to write my tests first, but I am having trouble for creating a test that touches my DataAccessor. I can't figure out how to fake it. I've done the extend the shipment class and override the Load() method; to continue testing the object. I feel as though I end up unit testing my Mock objects/stubs and not my real objects. I thought in TDD the unit tests were supposed to hit ALL of the methods on the object; however I can never seem to test that Load() code only the overriden Mock Load

My tests were write an object that contains a list of orders based off of shipment number.

I have an object that loads itself from the database.

public class Shipment
{
 //member variables
 protected List<string> _listOfOrders = new List<string>();
 protected string _id = "" 

 //public properties
 public List<string> ListOrders
 {
    get{ return _listOfOrders; }
 }

 public Shipment(string id)
 {
     _id = id;
     Load();
 }

 //PROBLEM METHOD
 // whenever I write code that needs this Shipment object, this method tries
 // to hit the DB and fubars my tests
 // the only way to get around is to have all my tests run on a fake Shipment object. 
 protected void Load()
 {
     _listOfOrders = DataAccessor.GetOrders(_id);
 }


}

I create my fake shipment class to test the rest of the classes methods .I can't ever test the Real load method without having an actual DB connection

public class  FakeShipment : Shipment
{

 protected new void Load()
 {
     _listOfOrders = new List<string>();
 }


}

Any thoughts? Please advise.

Dave

+1  A: 

make it

 public Shipment(DataAccessor da, string id)
 {
     _da = da;
     _id = id;
     Load();
 }

 protected void Load()
 {
     _listOfOrders = _da.GetOrders(_id);
 }

DataAccessor should be probably be an interface.

btw, those protected data members smell like rotten fish.

just somebody
yeah I made those protected so I could muck with them in my fake objects... I'm guessing thats probably terrible practice.
Dave Hanson
+3  A: 

I'm assuming DataAccessor is currently a static class.
The first step would be to create an abstraction for the DataAccessor by creating an interface.

IDataAccessor

Then you have two options, make IDataAccessor a constructor dependency see below:

public class Shipment
{
  private readonly IDataAccessor dataAccessor; 
  public Shipment(IDataAccessor dataAccessor) 
  {
    this.dataAccessor = dataAccessor;  
  }
}

Or use the Double Dispatch method shown below:

 public void Load(IDataAccessor dataAccessor)
 {
     _listOfOrders = dataAccessor.GetOrders(_id);
 }

Then in your Unit Tests you would use a stub implementation for the IDataAccessor.

willbt
Another way would be to just pass in the orders in the constructor.
kyoryu
Thanks for the information. I'm going to go with the first one and hope it improves my testability.
Dave Hanson