CHAPTER 18 ■ TESTING WITH PHPUNIT
use the convenience methods in TestCase to generate your matcher). The matcher defines the
cardinality of the expectation, that is, the number of times a method should be called.
Table 18–3 shows the matcher methods available in a TestCase class.
Table 18–3. Some Matcher Methods
TestCase Method Match Fails Unless...
any( ) Zero or more calls are made to corresponding method (useful for stub
objects that return values but don’t test invocations).
never( ) No calls are made to corresponding method.
atLeastOnce( ) (^) One or more calls are made to corresponding method.
once( ) A single call is made to corresponding method.
exactly( $num ) $num calls are made to corresponding method.
at( $num ) A call to corresponding method made at $num index (each method call
to a mock is recorded and indexed).
Having set up the match requirement, I need to specify a method to which it applies. For instance,
expects() returns an object (PHPUnit_Framework_MockObject_Builder_InvocationMocker, if you must
know) that has a method called method(). I can simply call that with a method name. This is enough to
get some real mocking done:
$store = $this->getMock("UserStore");
$store->expects( $this->once() )
->method('notifyPasswordFailure');
I need to go further, though, and check the parameters that are passed to notifyPasswordFailure().
The InvocationMocker::method() returns an instance of the object it was called on. InvocationMocker
includes a method name with(), which accepts a variable list of parameters to match. It also accepts
constraint objects, so you can test ranges and so on. Armed with this, you can complete the statement
and ensure the expected parameter is passed to notifyPasswordFailure().
$store->expects($this->once() )
->method('notifyPasswordFailure')
->with( $this->equalTo('[email protected]') );
You can see why this is known as a fluent interface. It reads a bit like a sentence: “The $store object
expects a single call to the notifyPasswordFailure() method with parameter [email protected].”
Notice that I passed a constraint to with(). Actually, that’s redundant—any bare arguments are
converted to constraints internally, so I could write the statement like this:
$store->expects($this->once() )
->method('notifyPasswordFailure')
->with( '[email protected]' );
Sometimes, you only want to use PHPUnit’s mocks as stubs, that is, as objects that return values to
allow your tests to run. In such cases you can invoke InvocationMocker::will() from the call to
method(). The will() method requires the return value (or values if the method is to be called