- Professional Skills
- Articles
- Bookmarklets
- Javascript Console For IE
- Neural Net Extension for Ruby
- Writing a PDF Generation Framework In Ruby
- Developing Mambo Components
- PayPal Website Payments Pro
- Bulk File Renaming
- Displaying a Maintenance Page
- Ruby: escape, unescape
- Clojure Tutorial For the Non-Lisp Programmer
- Complex mocking with PHPUnit
- PHP Coding Tips
- Simple CRUD Application
- External Links
- Recent posts
Complex mocking with PHPUnit
Submitted by moxley on Fri, 2008-05-09 22:04
PHPUnit provides an API for creating Mock Objects and testing code with them. It is fairly flexible, but there are some things it can't do without breaking out of the recommended fluid API and using the mock framework's classes directly.
To compound the problem, the documentation is a bit too brief, and it leaves out the description of the underlying mock framework classes. The PHPUnit API documentation isn't much help, but it is a starting point.
What I wanted to do is test to see if a method on an object was called twice, but with different parameters each time. PHPUnit's mock API has no problem checking to see if the method was called twice with the same parameters both times, and it would look like this:
$uploadLog = $this->getMock('UploadLog', array('addInProgress'));
$uploadLog->expects($this->exactly(2))
->method('addInProgress')
->with($param1);
// ... Run the code that calls $uploadLog->addInProgress()
In the code I was testing, the parameters differed between the two calls. For testing that, I hoped that this would work:
$uploadLog = $this->getMock('UploadLog', array('addInProgress'));
$uploadLog->expects($this->once())
->method('addInProgress')
->with($param1);
$uploadLog->expects($this->once())
->method('addInProgress')
->with($param2);
// ... Run the code that calls $uploadLog->addInProgress()
Alas, it doesn't work. The test fails when the method is called the second time. PHPUnit complains that the method was called more than one time, regardless of the fact that the parameters were different.
Digging into the PHPUnit's API docs and source code, I developed a solution:
$uploadLog = $this->getMock('UploadLog', array('addInProgress'));
// ... Run the code that calls $uploadLog->addInProgress()
// Check invocations of $uploadLog->addInProgress()
$mocker = $uploadLog->getInvocationMocker();
$invocation = new PHPUnit_Framework_MockObject_Invocation(
$uploadLog,
get_class($uploadLog),
'addInProgress',
array($param1));
$matches = $mocker->matches($invocation);
$this->assertEquals(1, count($matches));
$invocation = PHPUnit_Framework_MockObject_Invocation($uploadLog,
get_class($uploadLog),
'addInProgress',
array($param2));
$matches = $mocker->matches($invocation);
$this->assertEquals(1, count($matches));
It is messy, but it works.


Cape Cod Cottage for Rent