Introducing fake objects to test your classes

Changing a code on a legacy project can be a big problem for some teams. There are two reasons for that.

The first reason is that the developer doesn’t fully understand the code and the project structure in order to know, exactly, where the change has to be made.

The second reason is more common one. The team can figure out where to change the code, but they could not be sure if it would have any side-effects and introduce bugs on other places in a project.

Because of the all things aforementioned, changes which in the well structured code should not take more then 5 to 10 minutes, could last more than a day in a legacy project.

The solution for the second problem is a refactoring technique called “Breaking dependencies”.

The best approach that will force you to do exactly that without even knowing, is trying to put classes under tests.

Let us take the look at an example of that.

class Player { private $db; public function __construct(DatabaseGateway $db) { $this->db = $db; } public function saveScore() { $this->db->savePlayerScore(); } }

In order to test this class, we have to make DatabaseGateway object, which might have its own dependencies. Therefore it would take us perhaps 50 lines of code to try and initialize all concrete classes so that we have testable Player class. That is too much of code, and the whole approach is wrong. Instead of that, we will do something called Interface Extraction.

Basically, we are going to make an interface that DatabaseGateway will implement. For our test we could make a fake object from that interface.

interface DatabaseGatewayInterface { public function savePlayerScore(); } class DatabaseGateway implements DatabaseGatewayInterface { public function savePlayerScore() { // save to db } } class DatabaseGatewayDummy implements DatabaseGatewayInterface { public function savePlayerScore() { // log to txt file or to local sqlite } }

Therefore, in our Player constructor, instead of concrete type, we expect interface.

class Player { ... public function __construct(DatabaseGatewayInterface $db) { $this->db = $db; } ... }

After that, it is easy to test the Player class. Let us take a look of setUp function.

class PlayerTest extends \PHPUnit_Framework_TestCase { private $player; public function setUp() { $db = new DatabaseGatewayDummy(); $this->player = new Player($db); } }

When your code depends on an interface, that dependency is usually very minor and unobtrusive. Your code doesn’t have to change unless the interface changes, and interfaces change far less then the code behind them.

The point of this is that you can edit classes that implement the interface, or add new classes that will do the same, all without impacting the code the interface uses.

We have just described dependency inversion principle and that was exactly what we did here in our small example.

The conclusion of our initial problem would be that decoupling modules (classes) will insure that you will change your code without the fear of breaking some part of code you are not even thinking about when doing a change.