Introducing Phake Mocking Framework

I have used PHPUnit heavily now for the last 4 years. As anyone that is heavily involved in writing Unit Tests knows, test doubles (commonly referred to as mock objects) are a necessary part of your toolbox. The mocking options that we used to have for PHP unit testing have traditionally been fairly limited and most all of them in some form or another were ports of JMock. The way PHP operates as well as some decisions made to more closely emulate how JMock does things lead to functionality in the existing mock library for PHPUnit that for some are a hassle. This ranges from PHPUnit implicitly calling the “mockee’s” constructor (you have to explicitly specify that you do not want to call the constructor) to the pain of trying to stub or verify multiple invocations of the same method with different parameters.

Over the last three years, my experience as well as the musing of some of my colleagues has led me to believe that a lot of what I don’t like about mocking in php is the result of the fundamental notions of combining stubbing with verification and setting expectations ahead of method calls instead of verifying that what you expected to happen has indeed happened. This was essentially proven to me over the last year and a half as I have been heavily working with Java code and as a result have been using the Mockito mocking library for Java. The result of this work is the Phake Mocking Framework.

Now I am fairly certain that at least 5 or 6 people (which may constitute everyone who reads this) are rolling their eyes by now. So instead of going further into why I like this style of mocking I’ll just show you how to use it. Phake was designed with PHPUnit in mind, however I don’t really see any reason why it couldn’t be used in other testing frameworks as well. It is on my roadmap to confirm support for other frameworks. In any case, I will be using PHPUnit for my examples.

This document assumes you already have a good understanding of the basics of mocking. If the terms ‘Mocking’, ‘Stubbing’, and ‘Test Doubles’ mean nothing to you, I would recommend checking out the following links:

Getting Started

You can get a copy of Phake from Github. If you are familiar and comfortable with with git you can just clone my repository. If you would rather avoid the trappings of Github, you can also download Phake’s latest release tarball. Either way will result in a directory with two subdirectories: src and test. You will want to move the contents of the src directory to somewhere in your include path (such as /usr/share/php). Once you have done this, you can simply include “Phake.php” in any of your tests or in your bootstrap script and you will be off to the races.


UPDATE!!!

I just set up a pear channel to distribute phake as well. So if you would like to install Phake using pear, just do the following:


To show you some of the basics of how to use this framework, I am going to write various bits of codes to mock, verify, stub, etc the following class:

Stubbing

You can also do conditional stubbing based on passed in parameters.

If a specific invocation or call of a mock object has not been stubbed, it will return null. This behavior is different than the default behavior of PHPUnit’s mocking framework. If you need the default PHPUnit behavior then you could use something called partial mocks. Partial mocks are setup to call the constructor of the class being mocked and for any call that has not been stubbed, the parent method will be called.

You can also specify on a per call basis that you want to call the parent, using the thenCallParent() method instead of thenReturn(). The different values you can use for stubbing are referred to as ‘Answers’. Here are a list of them and what they will do when a matching invocation is called:

  • thenReturn(mixed $var) – Will return the exact value passed in.
  • thenCallParent() – Will return the results of calling the mocked parent method.
  • thenThrow(Exception $e) – Will throw $e.
  • captureReturnTo(&$variable) – Acts exactly like thenCallParent() however it also captures the value that the parent returned to $variable. This allows you to run assertions. This comes in very handy for testing legacy code with protected or private factory methods whose return values are never returned out of the tested method’s scope.

The other thing to take note of stubbing is that any PHPUnit constraints are supported.

This gives you the same kind of stubbing flexibility that you have present in PHPUnit.

Verification

Verifying that methods on your stub are called is starkly different then how it is done in PHPUnit. The most apparent symptom of this difference is that you verify calls after the calls to your test methods have been made.

You of course have the same matching functionality at your disposal.

By default, verify only allows a single matching invocation. You can also specify that a specific number of invocations should be allowed.

You can also use Phake::atLeast($n) and Phake::atMost($n) instead of Phake::times($n).

You can also specify that you don’t expect there to be any interactions with a mock.

I am sure you noticed the comment that Phake::verifyNoInteraction() only verifies that no calls were made up to that point. You can essentially freeze a mock with another method

There are a few more advanced things you can do with something called argument captors.

This is a very pedestrian example, but it is not that uncommon for fairly complicated objects to passed in and out of methods. Argument capturing allows you to much more succinctly assert the state of those types of parameters. It is definitely overkill for asserting scalar types or simple objects.

More to Come

This really does cover the very basics of the Phake framework. In the coming days I will be putting out smaller more focused articles discussing some of the specific functionality. In the meantime I would love to get some feedback from anyone who is brave enough to play with this. My future roadmap basically involves shoring up the current code base a little bit more, adding a few pieces of missing or suboptimal functionality (I’m not so sure I have implemented ‘consecutive calls’) but I anticipate releasing an RC version no later than the end of January. Also, I am currently using and monitoring the issue tracker for Phake at github, so if you have some functionality you would like or find any bugs in your exploring, you can also open an issue there. Also, if you would like to help out with contributions, they are certainly welcome.

This entry was posted in PHP, PHP Testing and tagged , , , . Bookmark the permalink.

24 Responses to Introducing Phake Mocking Framework

  1. Pingback: Tweets that mention Introducing Phake Mocking Framework | Digital Sandwich -- Topsy.com

  2. Hi there,

    In general i am not a fan of reinventing the wheel but i have to say i like your approach!

    I also think that calling constructor by default is a problem as if you are mocking you call constructor quite rarely.

    Looks really nice, thanks for a post. keep us posted on how is the project evolving etc.

    art

  3. WC says:

    I use mock objects a lot with PHPUnit and this looks like it addresses a lot of the issues I had. I look forward to using this on my personal projects soon, and on my work projects later when it’s a little more tested. :)

  4. Adrian says:

    Over the last month I was evaluating some Java Mock Frameworks (especially Mockito) and I really liked the notation used there compared to PHPUnit mocks. Thanks a lot for your work. It’s looking really good and I’ll definitely look into it when I’ve got some spare time.

  5. Pingback: Mike Lively’s Blog: Introducing Phake Mocking Framework | Development Blog With Code Updates : Developercast.com

  6. That’s a very good Api. You save from one to two method calls for each mock, which is quite a lot. Also explicit verification of mocks is something you would want to have available in some cases.
    However you should set up a Pear channel to distribute it, so that Phake can easily be installed along with PHPUnit in development machines.

  7. Tarjei Huse says:

    Yay!

    I’ve been looking for something like this for quite a long time. I love the way the partial mocks work.

    I’m looking forward to testing Phake.

  8. Pingback: Pear Channel set up for Phake | Digital Sandwich

  9. Chen Kinnrot says:

    Awesome, I really like the capability of capture, most of the time I work with C#,
    and I hadn’t seen it in the popular mocking frameworks.

  10. daniel says:

    Looks nice – I never liked PHPUnit mocks either…I will check out Phake in my pet project to see how exactly it replaces PHPUnit mocks in my tests.
    On another note – do you have any plans for DBUnit? It’s been quite some time since the last update. Some time ago sb merged external patches, which actually break postgresql functionality. I wonder if you plan to maintain this code? Issues page seemed to be dead last time I checked, which is a pity.

    • Mike Lively says:

      I have not messed with DBUnit in a while as you have noticed. I should take a look at some of the outstanding issues and see if I can take care of them. The issues should still be active I think they were just moved to github. I will try to take a look at what happened with postgres though I will admit that I am not very postgres savvy :(. If you have a reproduction test case that would be nifty.

      • daniel says:

        AFAIR some guy on github “simplified” information schema query for postgresql, removing left join and thus broke it for more complex table schemas (with > 1 primary key or something similar) and sb merged it (sometime around 3.5).
        I’ll try to send the test case to github issues – I actually was about to do it the moment I found the problem, but the was no activity in dbunit for a long time, so I thought I would just waste my time.
        Do you actually use DBUnit in your own projects?

        • Mike Lively says:

          Yes, I actually developed it so I could use it at the company I work for. If I remember right, I added the initial postgres support, but it was pretty blind development as I have never actually used postgres :P

  11. Steve Clay says:

    I’m comfortable using mocks in SimpleTest but will give this a whirl when I do more work with PHPUnit. The API looks great.

    In your code sample, I’d split up one of your one-liners for clarity:

    //Matches any call to subtract() where the passed in value < 42
    $phpUnitConstraint = $this->lessThan(42);
    Phake::when($mock)->subtract($phpUnitConstraint)->thenReturn(29);

  12. daniel says:

    OK, I’ve just tried it and I love it ;) Pretty cool replacement for PHPUnit mocks. Though I had to edit the source code to make it work for me – added to issues at github.

  13. Hey, great work, I don’t like PHPUnit Mocking system also. But have you already seem the work Padraic did with Mockery? https://github.com/padraic/mockery

    • Mike Lively says:

      I have looked at the api but it has some of the same methodology and concepts behind it that I don’t really care for. There is nothing technically wrong with it, just a matter of preference. The biggest one being that I prefer to verify the calls to mocks after the test is exercised.

  14. 2011: Year Of The Mock Object ;)

    Yes, I am the one developing Mockery. As you noted above, there are a lot of preferences around mocking, a lot of approaches, and a lot of strategies to achieve it. I think it’s great to see another library make an appearance. While both are technically sound, it finally puts on the horizon the likelihood that PHPers can avail of several mocking/stubbing/spying options depending on their tastes and needs or even familiarity with options across other languages. Which would finally put us on an even footing with Ruby/Java/Python when it comes to mock objects. Keep it up!

  15. Pingback: Mockery 0.7.1 Released – It’s a Test Double Framework | Pádraic Brady

  16. WC says:

    When setting the return value, is there a way to specify a callback function instead? I don’t use that often with PHPUnit, but when I do, it’s quite necessary.

  17. Erin says:

    Great work on Phake! I’d really love to see it become the de-facto standard, as it just makes a lot more sense, compared to the way that PHPUnit’s mocks work.

    One thing that’s not mentioned as a benefit over PHPUnit, that I love, is the ability to use identicalTo() when verifying arguments to a method call. There’s currently a limitation in PHPUnit’s mocking system that prevents this, and it just feels right to be able to do so without filthy hax.

    Thanks again :)

  18. Pingback: Frameworks de Tests Doubles en PHP (y III)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">