Faster dependency mocking 01
October 2, 2014
While I'm pretty satisfied with the dependency mocking done by the tad_DependencyMocker
class that's built in the tdd-helpers package I'd like it to have small, or better none, documentation maintenance footprint.
The maintenance problem
Right now the tad_DependencyMocker
class will pick up public
methods dependencies from their documentation blocks; ideally up to date those doc-blocks would defina a @depends
notation explicitating a method dependencies like
// file SomeClass.php
public function SomeClass{
protected $a;
protected $b;
/**
* @param A $a
* @param B $b
*
* @depends A, B
*/
public function __construct(A $a, B $b){
$this->a = $a;
$this->b = $b;
}
/**
* someMethod description.
*
* @param C $c
* @param D $d
*
* @return int
*
* @depends C, D
*/
public function someMethod(C $c, D $d){
$this->a->aMethod();
$this->b->bMethod();
$c->cMethod();
$d->dMethod();
return 1;
}
}
This way the documentation block become something to manually maintain and keep up to date; while public
methods should be documented I also would very much like to omit those and still reap the benefits of a smart dependency mocker.
Scope of the dependency mocker
I'd building the dependency mocker to allow me some benefits and learn something in the process.
Ready to use PHPUnit mock objects
While there will always be some test specific setup to do I'd like to automate what's automatable and go over common tasks just once. Like DRY but on a multi-class level.
Write as little as possible
Code and doc all account as "writing"; if I have to maintain it, be it code or documentation, then I want it to be as automated as possible.
Furthermore any line of code, or doc, I do not write is a line of code not possibly generating a bug.
Gamification
Test-driven development (TDD) is all about gamifying the developing experience and moving from "red lights" to "green lights" writing as little as possible but I think I can "gamify me" to an higer level.
That's border line folly but as much as I like to develop driven by test I sometimes eschew good design principles in favor of speed (as in "time took to develop"). I can let go a small part of the "speed" part if I can get good design in return.
Ideally object dependendencies should be given to an object in any of these 3 ways:
- a constructor methods -
__construct
or static constructors of sorts - in accessor methods -
set
- as method parameters - e.g. a filter object instance
If I ever get my object dependencies anywhere else then I'm writing less testable, or not testable at all, code.
I will "force" myself into defining dependencies in a proper way promising me a "lightspeed fast" dependency mocking in return.
From the end
Current dependency mocker interface reads like this given the SomeClass
above:
// file SomeClassTest.php
class SomeClassTest extends PHPUnit_Framework_TestCase{
public function testSomeMethod(){
extract(tad_DependencyMocker::on('SomeClass')
->forMethods(array('__construct', 'someMethod'))
->getMocksArray());
$A->expects($this->once())
->method('aMethod')
$B->expects($this->once())
->method('bMethod')
$C->expects($this->once())
->method('cMethod')
$D->expects($this->once())
->method('dMethod')
$sut = new SomeClass($A, $B);
$sut->someMethod($C, $D);
}
}
and while I'm not changing that I'd like to free the mocker of documentation dependencies and be able to use this same interface on SomeClas
even if it's written like this (aka "no doc blocks"):
// file SomeClass.php
public function SomeClass{
protected $a;
protected $b;
public function __construct(A $a, B $b){
$this->a = $a;
$this->b = $b;
}
public function someMethod(C $c, D $d){
$this->a->aMethod();
$this->b->bMethod();
$c->cMethod();
$d->dMethod();
return 1;
}
}
which is probably what I will be dealing with the most during TDD rather than well documented code.
Next
Will move into building an intelligent parameter parsing in the mocker and test its limits.