This post originated from an RSS feed registered with PHP Buzz
by Sebastian Bergmann.
Original Post: Fluent Interface in PHPUnit 3.0
Feed Title: Sebastian Bergmann
Feed URL: http://sebastian-bergmann.de/
Feed Description: Geek by nature, PHP by choice.
A good example of a fluent interface is the API of jMock:
"Good fluent APIs take a while to build. If you want a much more thought out example of a fluent API take a look at JMock. JMock, like any mocking library, needs to create complex specifications of behavior. There have been many mocking libraries built over the last few years, JMock's contains a very nice fluent API which flows very nicely." (Martin Fowler)
PHPUnit 3.0 provides the same fluent interface for configuring its Mock Objects (because PHPUnit's implementation of Mock Objects is a port of jMock).
Here is an example that shows how to test that a Subject notifies its Observers correctly:
<?php
require_once 'PHPUnit2/Extensions/ExceptionTestCase.php';
class ObserverTest extends PHPUnit2_Framework_TestCase
{
public function testUpdateIsCalledOnce()
{
// Create a Mock Object for the Observer class
// mocking only the update() method.
$observer = $this->getMock('Observer', array('update'));
// Set up the expectation for the update() method
// to be called only once and with the string 'something'
// as its parameter.
$observer->expects($this->once())
->method('update')
->with($this->equalTo('something')
);
// Create a Subject object and attach the mocked
// Observer object to it.
$subject = new Subject;
$subject->attach($observer);
// Call the doSomething() method on the $subject object
// which we expect to call the mocked Observer object's
// update() method with the string 'something'.
$subject->doSomething();
}
}
?>
In essence, this means that you do not need to create several temporary objects -- for instance one to specify that you expect the update() method to be called and another for the expected parameter -- and wire them together afterwards to configure expectations.
Instead, you chain method calls as shown in the above example. This leads to more readable and "fluent" code.