11-1. Self-Shunting
Sometimes you need to check that an object has been called correctly. You can create a complete stub of the object to be called, but that can make it inconvenient to check for correct results. A simpler solution is to apply the self-shunt pattern and use the test-case object itself as a stub. The term selfshunting is taken from the medical practice of installing a tube that takes blood from an artery and returns it to a vein to provide a convenient place for injecting drugs.
Here is an example: suppose we want to test that the correct method is called on an object that observes another object. First, we make our test-case class an implementor of Observer:
class ObserverTest extends PHPUnit2_Framework_TestCase
implements Observer{
}
Next, we implement the one Observer method, update( ), to check that it is called when the state of the observed Subject object changes:
public $wasCalled = FALSE;
public function update(Subject $subject) {
$this->wasCalled = TRUE;
}
Now, we can write our test. We create a new Subject object and attach the test object to it as an observer. When the state of the Subject changesfor instance, by calling its doSomething( ) methodthe Subject object has to call the update( ) method on all objects that are registered as observers. We use the $wasCalled instance variable that is set by our implementation of update( ) to check whether the Subject object does what it is supposed to do:
public function testUpdate( ) {
$subject = new Subject;
$subject->attach($this);
$subject->doSomething( );
$this->assertTrue($this->wasCalled);
}
Notice that we create a new Subject object instead of relying on a global instance. Stubbing encourages this style of design. It reduces the coupling between objects and improves reuse.
If you are not familiar with the self-shunt pattern, the tests can be hard to read. What is going on here? Why is a test case also an observer? But once you get used to the idiom, the tests are easy to read. Everything you need to understand a test is in one class.
|