In a message I sent a few days ago:
Test Driven Development Fakes Are Faking me out!
I was lamenting that some tests I was trying to write using a fake testing object, simply were returning the values that I needed to pass the test.
I’ll use a small bit of my objects and interfaces to show you what I mean:
Now what we are seeing above is the original Order_Status module. It used to have it’s own functionality attached to the IsLineGroupReadOnly public function that would query the database for the conditions necessary to determine whether the given line group for the order was read only.
I needed this to return true for a test so I created an interface which you see is returned by the StatWrap function and defaults to ECI_StatusDbSourced which implements the interface and now has the code that talks to the database.
I also created two test classes called:
T_StatusConcreteGroupLinesAllOpen
T_StatusConcreteGroupLinesReadOnly
And each of them simply implemented that IsLineGroupReadOnly to return false in the first function and true in the second function.
What happened here though, is that although that works, I ended up creating functions that aren’t really testing the business logic. Here is the code with the business logic and database call combined:
In this case if you blink you’ll miss the database and business logic intermingling, but notice that I’m checking the database call result to see if it’s greater than 0.
What I ended up doing was to move the comparison back into the OrderStatus object to keep the business logic there and changed the interface function to a new function that says it is counting the lines in the group for read only and valid lines:
And then the original Order_Status changed the public function IsLineGroupReadOnly to use the wrapper to get the count of the lines which is a pure database call.
And what this allows me to do is to create fakes that can return the number of lines I want vs just overriding the function that contains the business logic to make it true or false.
I can now fake the database itself and feed the values into the same logic object and I will be testing the logic itself based on what’s in the database vs what I want the logic to tell me.