Mock Objects in PHPUnit

Sebastian Bergmann » 05 July 2005 » in New Features » 9 Comments

While I am preparing the PHPUNIT_2_3 CVS branch for a release of PHPUnit 2.3.0 alongside PHP 5.1.0, I recently started working on support for Mock Objects in PHPUnit.

Suppose you have the following class Foo:
class Foo {
    public function bar() {
    }
}
?>
You can now write a test case that checks whether or not the bar() method gets called on an object of the Foo class:
require_once 'PHPUnit2/Framework/TestCase.php';

class FooTest extends PHPUnit2_Framework_TestCase {
    public function testBarGetsCalled() {
        $mock = $this->getMockObject('Foo');
        $mock->__expectAtLeastOnce('bar');
        $mock->bar();
    }
}
?>
The test above will succeed when the bar() method gets called at least once on the $mock object inside the scope of the testBarGetsCalled() method.

The getMockObject('Foo') call generates a class MockFoo (the Mock Object class for Foo) that extends from Foo and the signatures of all public methods are copied from Foo to MockFoo. In addition, a couple of MockObjects API methods are added to the MockFoo class:
  • __expectArguments($method, $arguments, $message = "")
  • __expectArgumentsAt($method, $arguments, $timing, $message = "")
  • __expectCallCount($method, $count, $message = "")
  • __expectMaximumCallCount($method, $count, $message = "")
  • __expectMinimumCallCount($method, $count, $message = "")
  • __expectNever($method, $message = "")
  • __expectOnce($method, $arguments = FALSE, $message = "")
  • __expectAtLeastOnce($method, $arguments = FALSE, $message = "")
  • __getCallCount($method)
  • __setReturn($method, $value, $arguments = FALSE)
  • __setReturnAt($method, $value, $timing, $arguments = FALSE)
These methods can be used to set up expectations and return values for the stubbed-out methods of the Mock Object.

The work on the Code Generator that generates the code for a Mock Object class is complete and I started to integrate the Mock Objects functionality into the PHPUnit framework.
Defined tags for this entry: , ,

Trackback specific URI for this entry

9 Comments to "Mock Objects in PHPUnit"

Display comments as (Linear | Threaded)
  1. Marcus Baker
    06/07/2005 at 01:29 Permalink
    Hm...those method signatures look familiar...

    yours, Marcus

    Reply

  2. andrew morton
    13/07/2005 at 00:38 Permalink
    why does the new version of phpunit require php 5.1? what new functionality does it require? i'm asking because it seems like it's going to be a while before 5.1 is in widespread use and i'd rather do my development on the version most users are going to be using. i don't want to worry about inadvertently adding incompatible code. i suppose i could setup a copy of php 5.1 along side 5.0 but that seems like a lot of trouble just for unit tests.

    maybe you could do a post explaining why 5.1?

    Reply

  3. Sebastian Bergmann
    13/07/2005 at 16:59 Permalink
    For instance, I wanted to use __autoload() in PHPUnit2 for a long time. I could not use it PHP 5.0, because then the tested code could not have an __autoload() method of its own. With the SPL's improved autoload facility in PHP 5.1 this is now possible.

    In the previous versions of PHPUnit2 I used a "backport" of PHP 5.1's AppendIterator written in PHP. This is no longer necessary with PHP 5.1.

    I also wanted to use other feature additions that are in PHP 5.1, like the Array typehint and the new exception classes of the SPL.

    Reply

  4. Justin Hendrickson
    25/07/2005 at 22:52 Permalink
    So how long until we can expect to see this in the CVS? I'm absolutely dying to try it. I nearly converted to SimpleTest just so I could get some database mapper tests done.

    Reply

  5. Sebastian Bergmann
    26/07/2005 at 06:57 Permalink
    It is in CVS as of yesterday.

    Reply

  6. Keith Roberts
    24/09/2007 at 16:13 Permalink
    Thanks for porting xunit to PHPUnit Sebastian. I'm pleased you are adding mock objects to PHPUnit as well. I want to get PHPUnit working with Phing. I don't think Phing supports simpletest. I prefer to use PHPUnit and stick with that.

    Kind Regards

    Keith

    Reply

  7. Tomas Liubinas
    25/10/2007 at 18:37 Permalink
    Did the functionality changed in recent versions, because this is what I get:
    Function '__setReturn' does not exist or is not acce
    ssable! (oxBase)

    And I can't say what version of phpUnit I am using, as for current version it displays:
    PHPUnit @package_version@ by Sebastian Bergmann.

    Greetings from Lithuania
    Tomas Liubinas

    Reply

  8. Sebastian Bergmann
    25/10/2007 at 19:06 Permalink
    The functionality you are refering to was never included in a production release of PHPUnit. Please refer to the documentation of PHPUnit for the Mock Object system that has been part of PHPUnit since PHPUnit 3.0.

    Reply

  9. Stuardo -StR- Rodríguez
    08/09/2008 at 15:04 Permalink
    Could you update or create a new post about mock tests? This post is obsolete and the oficial documentation is to short..

    Thanks

    Reply

1 Trackback to "Mock Objects in PHPUnit"

  1. Bob's Blog 05/07/2005 at 20:36
    Looks like Sebastian is making some exciting progress implementing mocks for PHPUnit2. He's gone a step further (which I think is great!) and implemented expectations on the Mock object itself- i.e. I can tell the mock object for class Foo that I exp...

Add Comment


To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Submitted comments will be subject to moderation before being displayed.