TDD friendly objects
September 26, 2014
I've refactored the tad_TestableObject
class I had presented in a previous post after some mileage to a simpler and more useful interface.
The problem
As I had stated in the above-mentioned post while I'd like to keep developing test-driven developed (TDD) code when possible I'd also like to make setting up per-method testing environments less of a chore.
Testing the methodOne
of this class
class ClassOne{
protected $d;
public function __construct(D $d){
$this->d = $d;
}
public function methodOne(A $a, BInterface $b, CInterface $c){
$a->method();
$b->method();
$c->method();
$this->d->method();
}
}
would require mocking instances of the A
and D
classes and the BInterface
and CInterface
interfaces like
// file ClassOneTest.php
public function test_methodOne_will_call_methods(){
$mockA = $this->getMock('A', array('method'));
$mockBInterface = $this->getMock('BInterface', array('method'));
$mockCInterface = $this->getMock('CInterface', array('method'));
$mockD = $this->getMock('D', array('method'));
$mockA->expects($this->once())->method('method');
$mockBInterface->expects($this->once())->method('method');
$mockCInterface->expects($this->once())->method('method');
$mockD->expects($this->once())->method('method');
$sut = new ClassOne($mockD);
$sut->methodOne();
}
I'd like some faster mocking.
Another solution
I've modified my original tad_TestableObject
class to define a static
method that allows getting mocked dependencies for one or more of its methods like
class ClassOne extends tad_TestableObject {
protected $d;
/**
* @depends D
*/
public function __construct(D $d){
$this->d = $d;
}
/**
* @depends A, BInterface, CInterface
*/
public function methodOne(A $a, BInterface $b, CInterface $c){
$a->method();
$b->method();
$c->method();
$this->d->method();
}
}
and would allow me to rewrite the test method above in a shorter form
// file ClassOneTest.php
public function test_methodOne_will_call_methods(){
$mockedDependencies = ClassOne::getMocksFor($this, array('__construct', 'methodOne'))
$mockDependencies->A->expects($this->once())->method('method');
$mockDependencies->BInterface->expects($this->once())->method('method');
$mockDependencies->CInterface->expects($this->once())->method('method');
$mockDependencies->D->expects($this->once())->method('method');
$sut = new ClassOne($mockD);
$sut->methodOne();
}
I feel like it's not cryptic to read and quite convenient. The tad_TestableObject
class is part of the tdd-helpers package.