<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Sebastian Bergmann - PHPUnit</title>
    <link>http://sebastian-bergmann.de/</link>
    <description></description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.5.3 - http://www.s9y.org/</generator>
    
    

<item>
    <title>GTAC 2010</title>
    <link>http://sebastian-bergmann.de/archives/893-GTAC-2010.html</link>
            <category>Presentations</category>
    
    <comments>http://sebastian-bergmann.de/archives/893-GTAC-2010.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=893</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=893</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;I have been invited to attend the &lt;a href=&quot;http://www.gtac.biz/&quot;&gt;5th Annual Google Test Automation Conference&lt;/a&gt;, better known as GTAC, in Hyderabad, India in October. I am very much looking forward to &lt;em&gt;discuss cutting edge challenges in test automation and evaluate potential solutions&lt;/em&gt;, especially with this year&#039;s focus on testability.&lt;/p&gt;&lt;p&gt;Another thing I like about this year&#039;s GTAC is that the participants are responsible for selecting the presentations for the conference. Here is my submission:&lt;/p&gt;&lt;dl&gt;&lt;dd&gt;&lt;h3&gt;Challenges in Unit Testing PHP Applications&lt;/h3&gt;&lt;p&gt;According to TIOBE, PHP is the most popular programming language after C/C++ and Java. The language has made strong inroads into large-scale, business-critical Web systems. In the six years since the release of PHP 5 -- which not only kickstarted the development of PHP-based frameworks for Web development but also the development of tools for dynamic and static testing techniques -- the PHP community as a whole has developed an increasing interest in developing software that delivers the best possible quality.&lt;/p&gt;&lt;p&gt;When PHP developers start to write unit tests they rarely find themselves without any constraints that are imposed by prior work of less than optimal quality. It is a well-known fact that writing unit tests for legacy code is hard. In the case of PHP it can be even harder: the legacy code has not only been written without testability in mind, but it may have been written for earlier versions of PHP that encouraged practices that make the code next to impossible to unit test.&lt;/p&gt;&lt;p&gt;PHPUnit, the de-facto standard framework for unit-testing PHP code, has some unique features not found in other xUnit test frameworks that allow the testing of untestable code. While developers should not use these features (as they are not required when writing tests for testable code), these features ease the pain of writing tests for legacy code and thus help developers get started with unit testing before they refactor the code for testability.&lt;/p&gt;&lt;p&gt;This session, presented by the creator of PHPUnit, highlights the challenges developers are facing when unit testing legacy PHP code. Some of these challenges will be familiar to developers that use other programming languages such as Java but they will see a new perspective on the problem and different approaches to solve it.&lt;/p&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;p&gt;Although I am hoping, of course, that my submission will be accepted by my peers, I know that GTAC will be valuable for me even if I do not get to present: the &quot;hallway track&quot; of GTAC 2008 was amazing.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Fri, 23 Jul 2010 15:20:35 +0200</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/893-guid.html</guid>
    <category>gtac</category>
<category>phpunit</category>

</item>
<item>
    <title>PHPUnit 3.5: Refactoring to Components</title>
    <link>http://sebastian-bergmann.de/archives/892-PHPUnit-3.5-Refactoring-to-Components.html</link>
            <category>Articles</category>
    
    <comments>http://sebastian-bergmann.de/archives/892-PHPUnit-3.5-Refactoring-to-Components.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=892</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=892</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;When you look at the list of changes for PHPUnit 3.5, you will see that many of them deal with refactoring to components. Here is an overview of these new components:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://github.com/sebastianbergmann/php-code-coverage&quot;&gt;PHP_CodeCoverage&lt;/a&gt;&lt;p&gt;The collection, processing, and rendering of code coverage information has been factored out into a separate component. A bit more information can be found &lt;a href=&quot;http://sebastian-bergmann.de/archives/886-Code-Coverage-Dashboard.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/sebastianbergmann/phpunit-mock-objects&quot;&gt;PHPUnit_MockObject&lt;/a&gt;&lt;p&gt;The functionality to automatically generate an object that can act as a test double for a specified original class has been factored out into a separate component. Do not worry, &lt;code&gt;getMock()&lt;/code&gt; and related methods will work just as they did in previous versions of PHPUnit. The refactoring, however, makes the usage of other mock object libraries (such as &lt;a href=&quot;http://github.com/padraic/mockery&quot;&gt;Mockery&lt;/a&gt; or &lt;a href=&quot;http://github.com/mlively/Phake&quot;&gt;Phake&lt;/a&gt;, for instance) easier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/sebastianbergmann/dbunit&quot;&gt;DbUnit&lt;/a&gt;&lt;p&gt;The database testing functionality that is provided by the DbUnit extension and the respective &lt;code&gt;DatabaseTestCase&lt;/code&gt; class has been moved to a separate component. Michael Lively Jr, the author of DbUnit, is now able to make releases of the database testing extension on a release schedule that is separate from PHPUnit itself, meaning that I will be even less involved in its development than I have before.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/sebastianbergmann/phpunit-selenium&quot;&gt;PHPUnit_Selenium&lt;/a&gt;&lt;p&gt;&lt;code&gt;SeleniumTestCase&lt;/code&gt;, the &lt;a href=&quot;http://seleniumhq.org/&quot;&gt;Selenium RC&lt;/a&gt; integration for PHPUnit, has been moved to a separate component to allow a release cycle separate from PHPUnit itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/sebastianbergmann/php-file-iterator&quot;&gt;File_Iterator&lt;/a&gt;, &lt;a href=&quot;http://github.com/sebastianbergmann/php-timer&quot;&gt;PHP_Timer&lt;/a&gt;, &lt;a href=&quot;http://github.com/sebastianbergmann/php-text-template&quot;&gt;Text_Template&lt;/a&gt;&lt;p&gt;Utility methods to collect files and report resource usage as well as a simple templating mechanism have been moved to separate components so that they can be reused by other tools such as &lt;a href=&quot;http://github.com/mayflowergmbh/PHP_CodeBrowser&quot;&gt;phpcb&lt;/a&gt;, &lt;a href=&quot;http://pear.php.net/package/PHP_CodeSniffer&quot;&gt;phpcs&lt;/a&gt;, &lt;a href=&quot;http://github.com/sebastianbergmann/phpcpd&quot;&gt;phpcpd&lt;/a&gt;, and &lt;a href=&quot;http://pdepend.org/&quot;&gt;pdepend&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; 
    </content:encoded>

    <pubDate>Fri, 23 Jul 2010 14:00:00 +0200</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/892-guid.html</guid>
    <category>phpunit</category>

</item>
<item>
    <title>PHPUnit 3.5 Beta 1</title>
    <link>http://sebastian-bergmann.de/archives/891-PHPUnit-3.5-Beta-1.html</link>
            <category>Announcements</category>
    
    <comments>http://sebastian-bergmann.de/archives/891-PHPUnit-3.5-Beta-1.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=891</wfw:comment>

    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=891</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;To celebrate the 15th birthday of PHP, I have released PHPUnit 3.5 Beta 1 today. The refactoring towards components is a &quot;new feature&quot; that is already visible upon installation:&lt;/p&gt;&lt;dl&gt;&lt;dd&gt;&lt;small&gt;&lt;pre&gt;sb@vmware ~ % pear install phpunit/PHPUnit-beta
phpunit/PHPUnit can optionally use PHP extension &quot;dbus&quot;
downloading PHPUnit-3.5.0beta1.tgz ...
Starting to download PHPUnit-3.5.0beta1.tgz (105,588 bytes)
........................done: 105,588 bytes
downloading DbUnit-1.0.0beta1.tgz ...
Starting to download DbUnit-1.0.0beta1.tgz (38,209 bytes)
...done: 38,209 bytes
downloading File_Iterator-1.2.1.tgz ...
Starting to download File_Iterator-1.2.1.tgz (3,225 bytes)
...done: 3,225 bytes
downloading Text_Template-1.0.0.tgz ...
Starting to download Text_Template-1.0.0.tgz (2,493 bytes)
...done: 2,493 bytes
downloading PHP_CodeCoverage-1.0.0beta1.tgz ...
Starting to download PHP_CodeCoverage-1.0.0beta1.tgz (108,640 bytes)
...done: 108,640 bytes
downloading PHP_Timer-1.0.0.tgz ...
Starting to download PHP_Timer-1.0.0.tgz (2,536 bytes)
...done: 2,536 bytes
downloading PHPUnit_MockObject-1.0.0beta1.tgz ...
Starting to download PHPUnit_MockObject-1.0.0beta1.tgz (15,816 bytes)
...done: 15,816 bytes
downloading PHPUnit_Selenium-1.0.0beta1.tgz ...
Starting to download PHPUnit_Selenium-1.0.0beta1.tgz (15,298 bytes)
...done: 15,298 bytes
downloading PHP_TokenStream-1.0.0beta1.tgz ...
Starting to download PHP_TokenStream-1.0.0beta1.tgz (7,023 bytes)
...done: 7,023 bytes
install ok: channel://pear.phpunit.de/File_Iterator-1.2.1
install ok: channel://pear.phpunit.de/Text_Template-1.0.0
install ok: channel://pear.phpunit.de/PHP_Timer-1.0.0
install ok: channel://pear.phpunit.de/PHP_TokenStream-1.0.0beta1
install ok: channel://pear.phpunit.de/PHP_CodeCoverage-1.0.0beta1
install ok: channel://pear.phpunit.de/PHPUnit-3.5.0beta1
install ok: channel://pear.phpunit.de/DbUnit-1.0.0beta1
install ok: channel://pear.phpunit.de/PHPUnit_MockObject-1.0.0beta1
install ok: channel://pear.phpunit.de/PHPUnit_Selenium-1.0.0beta1&lt;/pre&gt;&lt;/small&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;p&gt;Happy Birthday PHP! And have fun testing (with) PHPUnit 3.5!&lt;/p&gt; 
    </content:encoded>

    <pubDate>Tue, 08 Jun 2010 10:20:00 +0200</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/891-guid.html</guid>
    <category>phpunit</category>
<category>release announcement</category>

</item>
<item>
    <title>Using PHPUnit from a Git Checkout</title>
    <link>http://sebastian-bergmann.de/archives/888-Using-PHPUnit-from-a-Git-Checkout.html</link>
            <category>Articles</category>
    
    <comments>http://sebastian-bergmann.de/archives/888-Using-PHPUnit-from-a-Git-Checkout.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=888</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=888</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;Users of PHPUnit frequently ask me questions such as &quot;&lt;em&gt;How do I use PHPUnit from a Git checkout?&lt;/em&gt;&quot; or &quot;&lt;em&gt;How do I run PHPUnit&#039;s own test suite?&lt;/em&gt;&quot; This article provides the answers to these questions.&lt;/p&gt;

&lt;h3&gt;Getting PHPUnit from Git&lt;/h3&gt;

&lt;dl&gt;&lt;dd&gt;&lt;small&gt;&lt;pre&gt;sb@thinkpad ~ % git clone git://github.com/sebastianbergmann/phpunit.git&lt;/pre&gt;&lt;/small&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;You now have a &lt;code&gt;phpunit&lt;/code&gt; directory in your current working directory that contains the branch for PHPUnit 3.5 (at the time of writing) because the &lt;code&gt;3.5&lt;/code&gt; branch is currently configured as the &lt;em&gt;default&lt;/em&gt; branch for the PHPUnit repository on GitHub. If you want to switch to the branch for PHPUnit 3.4, for instance, you can use&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;small&gt;&lt;pre&gt;sb@thinkpad phpunit % git checkout -b 3.4 origin/3.4&lt;/pre&gt;&lt;/small&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;This tells Git to create a new local branch of name &lt;code&gt;3.4&lt;/code&gt; (&lt;code&gt;-b 3.4&lt;/code&gt;) that is set up to track the remote branch &lt;code&gt;3.4&lt;/code&gt; from &lt;code&gt;origin&lt;/code&gt; (&lt;code&gt;origin/3.4&lt;/code&gt;). Git automatically switches to the newly created local branch. Using&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;small&gt;&lt;pre&gt;sb@thinkpad phpunit % git checkout 3.5&lt;/pre&gt;&lt;/small&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;you can switch back to the branch for PHPUnit 3.5.&lt;/p&gt;

&lt;h3&gt;Running PHPUnit from a Git checkout&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code&gt;phpunit&lt;/code&gt; directory you will find the &lt;code&gt;phpunit.php&lt;/code&gt; script. Using this script you can invoke the &lt;a href=&quot;http://www.phpunit.de/manual/current/en/textui.html&quot;&gt;PHPUnit TextUI test runner&lt;/a&gt;:&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;small&gt;&lt;pre&gt;sb@thinkpad ~ % phpunit/phpunit.php
PHPUnit @package_version@ by Sebastian Bergmann.
.
.
.&lt;/pre&gt;&lt;/small&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;The &lt;code&gt;@package_version@&lt;/code&gt; placeholder string for the version information makes it clear that a non-release version of PHPUnit is being used. Upon installation, the PEAR Installer replaces this placeholder string with the relevant information.&lt;/p&gt;

&lt;h3&gt;Running PHPUnit&#039;s Own Test Suite&lt;/h3&gt;

&lt;p&gt;Running PHPUnit&#039;s own test suite is as easy as invoking &lt;code&gt;phpunit&lt;/code&gt; in the checkout directory:&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;small&gt;&lt;pre&gt;sb@thinkpad phpunit % phpunit                  
PHPUnit @package_version@ by Sebastian Bergmann.

............................................................  60 / 681
............................................................ 120 / 681
............................................................ 180 / 681
............................................................ 240 / 681
............................................................ 300 / 681
............................................................ 360 / 681
............................................................ 420 / 681
............................................................ 480 / 681
................................SSSSSSSSSSSSSSSSSSSSSSSSSSSS 540 / 681
SSSS.......................................S................ 600 / 681
............................................................ 660 / 681
.....................

Time: 27 seconds, Memory: 56.25Mb

OK, but incomplete or skipped tests!
Tests: 681, Assertions: 1459, Skipped: 33.

Writing code coverage data to XML file, this may take a moment.

Generating code coverage report, this may take a moment.&lt;/pre&gt;&lt;/small&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;The above works because there is an XML configuration for PHPUnit (&lt;code&gt;phpunit.xml.dist&lt;/code&gt;) in the directory that contains information about which tests to run and what logfiles to produce.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Thu, 15 Apr 2010 13:35:00 +0200</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/888-guid.html</guid>
    <category>git</category>
<category>phpunit</category>

</item>
<item>
    <title>Code Coverage Dashboard</title>
    <link>http://sebastian-bergmann.de/archives/886-Code-Coverage-Dashboard.html</link>
            <category>Announcements</category>
    
    <comments>http://sebastian-bergmann.de/archives/886-Code-Coverage-Dashboard.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=886</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=886</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;Almost &lt;a href=&quot;http://github.com/sebastianbergmann/php-code-coverage/commit/aa0aaabc6c8faeec350c558258f7460b491239b1&quot;&gt;a year ago&lt;/a&gt; I started to &lt;a href=&quot;http://en.wikipedia.org/wiki/Refactoring&quot;&gt;factor out&lt;/a&gt; all the code that deals with &lt;a href=&quot;http://en.wikipedia.org/wiki/Code_coverage&quot;&gt;code coverage&lt;/a&gt; in &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt; and put it into a separate component. The name of this component is &lt;a href=&quot;http://github.com/sebastianbergmann/php-code-coverage&quot;&gt;PHP_CodeCoverage&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;PHP_CodeCoverage is a library that provides collection, processing, and rendering functionality for PHP code coverage information. Its architecture has support for multiple backends for collecting code coverage information (currently only support for &lt;a href=&quot;http://xdebug.org/&quot;&gt;Xdebug&lt;/a&gt; is implemented) and for reporting code coverage information (for instance using Clover XML or as an HTML report).&lt;/p&gt;&lt;p&gt;As mentioned earlier, the HTML report that is generated by PHP_CodeCoverage shows the &lt;a href=&quot;http://sebastian-bergmann.de/archives/877-CRAP-in-PHPUnit-3.5.html&quot;&gt;CRAP Index&lt;/a&gt; software metric for each function or method. Today I built on this earlier development and added a &quot;dashboard view&quot; to the HTML report that shows the following software metrics:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Class Coverage Distribution&lt;/strong&gt;: This is a bar chart that shows how many classes have 0%, ..., 100% code coverage&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Class Complexity&lt;/strong&gt;: This is a scatter chart that shows the coverage (X axis) and the complexity (Y axis) of the classes&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Top Project Risks&lt;/strong&gt;: This is list of the classes with the highest &lt;a href=&quot;http://sebastian-bergmann.de/archives/877-CRAP-in-PHPUnit-3.5.html&quot;&gt;CRAP Index&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Least Tested Methods&lt;/strong&gt;: This is the list of the least tested methods&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;You can see an example of the dashboard view below:&lt;/p&gt;&lt;a href=&quot;http://www.flickr.com/photos/sebastian_bergmann/4486651271/&quot; title=&quot;PHP_CodeCoverage Dashboard View by Sebastian Bergmann, on Flickr&quot;&gt;&lt;img src=&quot;http://farm3.static.flickr.com/2780/4486651271_e3dd746234.jpg&quot; width=&quot;500&quot; height=&quot;267&quot; alt=&quot;PHP_CodeCoverage Dashboard View&quot; /&gt;&lt;/a&gt; 
    </content:encoded>

    <pubDate>Sat, 03 Apr 2010 19:15:00 +0200</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/886-guid.html</guid>
    <category>code coverage</category>
<category>php</category>
<category>php_codecoverage</category>

</item>
<item>
    <title>Stubbing Hard-Coded Dependencies</title>
    <link>http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html</link>
            <category>Articles</category>
    
    <comments>http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=885</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=885</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;&lt;strong&gt;This article is part of a series on testing untestable code:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html&quot;&gt;Testing private methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html&quot;&gt;Testing code that uses singletons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html&quot;&gt;Stubbing static methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html&quot;&gt;Stubbing hard-coded dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_test&quot;&gt;unit test&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Mock_Object&quot;&gt;mock objects&lt;/a&gt; can simulate the behavior of complex, real (non-mock) objects and are therefore useful when a real object is difficult or impossible to incorporate into a unit test.&lt;/p&gt;
&lt;p&gt;A mock object can be used anywhere in the program where the program expects an object of the mocked class. However, this only works as long as the object can be passed into the context where the original object is used.&lt;/p&gt;
&lt;p&gt;Consider the following example:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;require_once&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;Bar.php&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingElse&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Bar&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingElse&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;*&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;With the code above, it is impossible to run a unit test for the &lt;code&gt;Foo::doSomething()&lt;/code&gt; method without also creating an object of &lt;code&gt;Bar&lt;/code&gt;. As the method creates the object of &lt;code&gt;Bar&lt;/code&gt; itself, we cannot inject a mock object in its stead.&lt;/p&gt;
&lt;p&gt;In a perfect world, code such as the above could be refactored using &lt;a href=&quot;http://en.wikipedia.org/wiki/Dependency_Injection&quot;&gt;Dependency Injection&lt;/a&gt;:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;require_once&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;Bar.php&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingElse&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Unfortunately, this is not always possible (not because of technical reasons, though).&lt;/p&gt;
&lt;p&gt;This is where the &lt;code&gt;set_new_overload()&lt;/code&gt; function that is provided by the &lt;a href=&quot;http://github.com/sebastianbergmann/php-test-helpers&quot;&gt;test_helpers&lt;/a&gt; extension for the PHP Interpreter comes into play. It can be used to register a &lt;a href=&quot;http://www.php.net/manual/en/language.pseudo-types.php&quot;&gt;callback&lt;/a&gt; that is automatically invoked when the &lt;code&gt;new&lt;/code&gt; operator is executed:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;require_once&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;Foo.php&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getMock&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;Bar&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;of&amp;#160;class&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;doSomethingElse&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;list&amp;#160;of&amp;#160;methods&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;constructor&amp;#160;arguments&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;BarMock&#039;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;for&amp;#160;mocked&amp;#160;class&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;set_new_overload&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;newCallback&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;tearDown&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;unset_new_overload&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;newCallback&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$className&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$className&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;Bar&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;BarMock&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$className&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testDoSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Lets run this unit test:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;PHPUnit 3.4.10 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 7.50Mb

OK (1 test, 2 assertions)&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;Note that there is no &lt;code&gt;*&lt;/code&gt; (printed from &lt;code&gt;Bar::doSomethingElse()&lt;/code&gt;) in the output above.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Tue, 16 Feb 2010 08:00:00 +0100</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/885-guid.html</guid>
    <category>phpunit</category>
<category>test_helpers</category>

</item>
<item>
    <title>Sharing Fixture Between Tests</title>
    <link>http://sebastian-bergmann.de/archives/884-Sharing-Fixture-Between-Tests.html</link>
            <category>New Features</category>
    
    <comments>http://sebastian-bergmann.de/archives/884-Sharing-Fixture-Between-Tests.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=884</wfw:comment>

    <slash:comments>6</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=884</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;There are few good reasons to share fixtures between tests, but in most cases the need to share a fixture between tests stems from an unresolved design problem.&lt;/p&gt;
&lt;p&gt;A good example of a fixture that makes sense to share across several tests is a database connection: you log into the database once and reuse the database connection instead of creating a new connection for each test. This makes your tests run faster.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit 3.5&lt;/a&gt; removes the &lt;a href=&quot;http://www.phpunit.de/manual/3.4/en/fixtures.html#fixtures.sharing-fixture&quot;&gt;fixture sharing&lt;/a&gt; feature of the &lt;code&gt;TestSuite&lt;/code&gt; class. It was tedious to use this feature as it required the usage of a custom &lt;code&gt;TestSuite&lt;/code&gt; class in addition to the test case class. Furthermore, its implementation was a &quot;hack&quot;.&lt;/p&gt;
&lt;p&gt;PHPUnit 3.4 introduced the &lt;code&gt;setUpBeforeClass()&lt;/code&gt; and &lt;code&gt;tearDownAfterClass()&lt;/code&gt; template methods that can be used in a test case class. These methods allow a much cleaner and simpler implementation of fixture sharing between tests of the same test case class:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;DatabaseTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$dbh&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;setUpBeforeClass&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$dbh&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PDO&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;sqlite::memory:&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;tearDownAfterClass&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$dbh&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;The example above uses the &lt;code&gt;setUpBeforeClass()&lt;/code&gt; and &lt;code&gt;tearDownAfterClass()&lt;/code&gt; template methods to connect to the database before the test case class&#039; first test and to disconnect from the database after the last test of the test case, respectively.&lt;/p&gt;
&lt;p&gt;It cannot be emphasized enough that &lt;a href=&quot;http://www.phpunit.de/manual/3.5/en/fixtures.html#fixtures.sharing-fixture&quot;&gt;sharing fixtures&lt;/a&gt; between tests reduces the value of the tests. The underlying design problem is that objects are not loosely coupled. You will achieve better results solving the underlying design problem and then writing tests using &lt;a href=&quot;http://www.phpunit.de/manual/current/en/test-doubles.html&quot;&gt;test doubles&lt;/a&gt;, than by creating dependencies between tests at runtime and ignoring the opportunity to improve your design.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Sun, 14 Feb 2010 10:40:10 +0100</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/884-guid.html</guid>
    <category>phpunit</category>
<category>shared fixture</category>

</item>
<item>
    <title>Stubbing and Mocking Static Methods</title>
    <link>http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html</link>
            <category>New Features</category>
    
    <comments>http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=883</wfw:comment>

    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=883</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;&lt;strong&gt;This article is part of a series on testing untestable code:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html&quot;&gt;Testing private methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html&quot;&gt;Testing code that uses singletons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html&quot;&gt;Stubbing static methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html&quot;&gt;Stubbing hard-coded dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;With PHPUnit 3.5 it will be possible to stub and mock static methods.&lt;/p&gt;
&lt;p&gt;Consider the class &lt;code&gt;Foo&lt;/code&gt;:&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;foo&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;When testing &lt;code&gt;Foo::doSomething()&lt;/code&gt; we want to decouple it from its dependency &lt;code&gt;Foo::helper()&lt;/code&gt;. With PHPUnit 3.5 and PHP 5.3 as well as consistent use of late static binding (using &lt;code&gt;static::&lt;/code&gt; instead of &lt;code&gt;self::&lt;/code&gt;) the following is possible:&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testDoSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getMockClass&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;Foo&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;of&amp;#160;class&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;helper&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;list&amp;#160;of&amp;#160;methods&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;staticExpects&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;helper&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;will&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;returnValue&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;bar&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;bar&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;The new &lt;code&gt;staticExpects()&lt;/code&gt; method works similar to the non-static &lt;code&gt;expects()&lt;/code&gt; variant.&lt;/p&gt;

&lt;p&gt;This approach only works for the stubbing and mocking of static method calls where &lt;em&gt;caller&lt;/em&gt; and &lt;em&gt;callee&lt;/em&gt; are in the same class. This is because &lt;a href=&quot;http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/&quot;&gt;static methods are death to testability&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&quot;&lt;em&gt;Unit-Testing needs seams, seams is where we prevent the execution of normal code path and is how we achieve isolation of the class under test. Seams work through polymorphism, we override/implement class/interface and then wire the class under test differently in order to take control of the execution flow. With static methods there is nothing to override. Yes, static methods are easy to call, but if the static method calls another static method there is no way to override the called method dependency.&lt;/em&gt;&quot;&lt;/blockquote&gt; 
    </content:encoded>

    <pubDate>Fri, 12 Feb 2010 06:30:00 +0100</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/883-guid.html</guid>
    <category>php</category>
<category>static methods</category>
<category>testing</category>

</item>
<item>
    <title>Testing Code That Uses Singletons</title>
    <link>http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html</link>
            <category>Articles</category>
    
    <comments>http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=882</wfw:comment>

    <slash:comments>12</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=882</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;&lt;strong&gt;This article is part of a series on testing untestable code:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html&quot;&gt;Testing private methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html&quot;&gt;Testing code that uses singletons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html&quot;&gt;Stubbing static methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html&quot;&gt;Stubbing hard-coded dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;I frequently quote &lt;a href=&quot;http://misko.hevery.com/&quot;&gt;Miko Hevery&lt;/a&gt; with&lt;/p&gt;
&lt;blockquote&gt;&quot;&lt;em&gt;&lt;a href=&quot;http://googletesting.blogspot.com/2008/05/tott-using-dependancy-injection-to.html&quot;&gt;It is hard to test code that uses singletons.&lt;/a&gt;&lt;/em&gt;&quot;&lt;/blockquote&gt;
&lt;p&gt;And then my audience asks me ...&lt;/p&gt;
&lt;h4&gt;Why is it hard to test code that uses singletons?&lt;/h4&gt;
&lt;p&gt;Lets have a look at the default implementation of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Singleton_pattern&quot;&gt;Singleton&lt;/a&gt; design pattern in PHP:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__clone&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;The code above declares a class that cannot be instantiated (or cloned) by a client using the &lt;code&gt;new&lt;/code&gt; (or &lt;code&gt;clone&lt;/code&gt;) operator(s). To get a reference to the only instance of the class one has to use the static method &lt;code&gt;getInstance()&lt;/code&gt;. Usually the code that uses the Singleton (which we will refer to as &lt;em&gt;client&lt;/em&gt;) is strongly coupled to the &lt;code&gt;getInstance()&lt;/code&gt; method:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Client&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;It is impossible to write a test for the &lt;code&gt;doSomething()&lt;/code&gt; method without also invoking the singleton&#039;s &lt;code&gt;getInstance()&lt;/code&gt; method. This means that we cannot get a fresh instance of the &lt;code&gt;Singleton&lt;/code&gt; class and thus have no guarantee that there are no side effects in multiple tests that interact with the singleton.&lt;/p&gt;
&lt;h4&gt;Dependency Injection&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Dependency_Injection&quot;&gt;Dependency Injection&lt;/a&gt; can help with decoupling the client from the &lt;code&gt;getInstance()&lt;/code&gt; method:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Client&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Instead of unconditionally invoking the &lt;code&gt;getInstance()&lt;/code&gt; method inside the &lt;code&gt;doSomething()&lt;/code&gt; we can now optionally pass in an instance of the &lt;code&gt;Singleton&lt;/code&gt; class. This allows us to pass in a &lt;em&gt;test-specific equivalent&lt;/em&gt; such as a &lt;em&gt;mock object&lt;/em&gt; or &lt;em&gt;stub&lt;/em&gt;:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;ClientTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testSingleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getMock&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;Singleton&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;of&amp;#160;class&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;list&amp;#160;of&amp;#160;methods&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;constructor&amp;#160;arguments&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;for&amp;#160;mocked&amp;#160;class&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;do&amp;#160;not&amp;#160;invoke&amp;#160;constructor&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&amp;#160;configure&amp;#160;$singleton&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$client&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$client&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;h4&gt;Alternative Singleton Implementations&lt;/h4&gt;
&lt;p&gt;Either as an alternative or in addition to rewriting the clients to optionally accept an instance of the &lt;code&gt;Singleton&lt;/code&gt; class as an argument, we can also rewrite the &lt;code&gt;Singleton&lt;/code&gt; class to make testing easier.&lt;/p&gt;
&lt;h5&gt;Resettable Singleton&lt;/h5&gt;
&lt;p&gt;The first approach is to add a &lt;code&gt;reset()&lt;/code&gt; method to the &lt;code&gt;Singleton&lt;/code&gt; class:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__clone&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Invoking the &lt;code&gt;reset()&lt;/code&gt; method causes the &lt;code&gt;getInstance()&lt;/code&gt; method to create a fresh object of the &lt;code&gt;Singleton&lt;/code&gt; class the next time it is called.&lt;/p&gt;
&lt;h5&gt;Singleton with Test Context&lt;/h5&gt;
&lt;p&gt;The second approach is to add a &lt;em&gt;testing context&lt;/em&gt; to the &lt;code&gt;Singleton&lt;/code&gt; class:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$testing&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__clone&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;||&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$testing&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Setting &lt;code&gt;Singleton::$testing = TRUE;&lt;/code&gt; causes the &lt;code&gt;getInstance()&lt;/code&gt; method to create a fresh object of the &lt;code&gt;Singleton&lt;/code&gt; class each time it is called.&lt;/p&gt;
&lt;h4&gt;PHPUnit Can Help, Too&lt;/h4&gt;
&lt;p&gt;PHPUnit has a &lt;a href=&quot;http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.global-state&quot;&gt;backup/restore mechanism for static attributes of classes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is yet another feature of PHPUnit that makes the testing of code that uses global state (which includes, but is not limited to, &lt;a href=&quot;http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html&quot;&gt;global and superglobal variables&lt;/a&gt; as well as static attributes of classes) easier.&lt;/p&gt;
&lt;h4&gt;Just Because You Can, Does Not Mean You Should&lt;/h4&gt;
&lt;p&gt;Yes, it is possible write testable code that uses singletons.&lt;br/&gt;This does not mean, however, that you should use them without thinking twice.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Thu, 11 Feb 2010 15:45:00 +0100</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/882-guid.html</guid>
    <category>dependency injection</category>
<category>php</category>
<category>singleton</category>
<category>testing</category>

</item>
<item>
    <title>Testing Your Privates</title>
    <link>http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html</link>
            <category>Articles</category>
    
    <comments>http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=881</wfw:comment>

    <slash:comments>15</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=881</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;&lt;strong&gt;This article is part of a series on testing untestable code:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html&quot;&gt;Testing private methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html&quot;&gt;Testing code that uses singletons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html&quot;&gt;Stubbing static methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html&quot;&gt;Stubbing hard-coded dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;No, not &lt;a href=&quot;http://en.wikipedia.org/wiki/Sex_organ&quot;&gt;those privates&lt;/a&gt;. If you need help with those, &lt;a href=&quot;http://oreilly.com/catalog/9780596801755/&quot;&gt;this book&lt;/a&gt; might help.&lt;/p&gt;
&lt;p&gt;One question I get over and over again when talking about &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_Testing&quot;&gt;Unit Testing&lt;/a&gt; is this:&lt;/p&gt;
&lt;blockquote&gt;&quot;&lt;em&gt;How do I test the private attributes and methods of my objects?&lt;/em&gt;&quot;&lt;/blockquote&gt;
&lt;p&gt;Lets assume we have a class &lt;code&gt;Foo&lt;/code&gt;:
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;baz&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingPrivate&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingPrivate&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;blah&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Before we explore how &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; attributes and methods can be tested directly, lets have a look at how they can be tested indirectly.&lt;/p&gt;
&lt;p&gt;The following test calls the &lt;code&gt;testDoSomething()&lt;/code&gt; method which in turn calls the &lt;code&gt;doSomethingPrivate()&lt;/code&gt; method:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*&amp;#160;@covers&amp;#160;Foo::doSomething&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*&amp;#160;@covers&amp;#160;Foo::doSomethingPrivate&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testDoSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;blah&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;The test above assumes that &lt;code&gt;testDoSomething()&lt;/code&gt; only works correctly when &lt;code&gt;testDoSomethingPrivate()&lt;/code&gt; works correctly. This means that we have indirectly tested &lt;code&gt;testDoSomethingPrivate()&lt;/code&gt;. The problem with this approach is that when the test fails we do not know directly where the root cause for the failure is. It could be in either &lt;code&gt;testDoSomething()&lt;/code&gt; or &lt;code&gt;testDoSomethingPrivate()&lt;/code&gt;. This makes the test less valuable.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt; supports reading &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; attributes through the &lt;code&gt;PHPUnit_Framework_Assert::readAttribute()&lt;/code&gt; method. Convenience wrappers such as &lt;code&gt;PHPUnit_Framework_TestCase::assertAttributeEquals()&lt;/code&gt; exist to express assertions on &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; attributes:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testPrivateAttribute&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertAttributeEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;baz&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;expected&amp;#160;value&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;bar&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;attribute&amp;#160;name&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;object&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;PHP 5.3.2 introduces the &lt;code&gt;ReflectionMethod::setAccessible()&lt;/code&gt; method to allow the invocation of &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; methods through the Reflection API:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*&amp;#160;@covers&amp;#160;Foo::doSomethingPrivate&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testPrivateMethod&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;ReflectionMethod&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;Foo&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;doSomethingPrivate&#039;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;setAccessible&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;&#039;blah&#039;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;invoke&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;In the test above we directly test &lt;code&gt;testDoSomethingPrivate()&lt;/code&gt;. When it fails we immediately know where to look for the root cause.&lt;/p&gt;
&lt;p&gt;I agree with Dave Thomas and Andy Hunt, who write in their book &quot;Pragmatic Unit Testing&quot;:&lt;/p&gt;
&lt;blockquote&gt;&quot;&lt;em&gt;In general, you don&#039;t want to break any encapsulation for the sake of testing (or as Mom used to say, &quot;don&#039;t expose your privates!&quot;). Most of the time, you should be able to test a class by exercising its public methods. If there is significant functionality that is hidden behind private or protected access, that might be a warning sign that there&#039;s another class in there struggling to get out.&lt;/em&gt;&quot;&lt;/blockquote&gt;
&lt;p&gt;So: Just because the testing of &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; attributes and methods is possible does not mean that this is a &quot;good thing&quot;.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Tue, 09 Feb 2010 13:00:59 +0100</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/881-guid.html</guid>
    <category>php</category>
<category>phpunit</category>
<category>reflection</category>

</item>
<item>
    <title>CRAP in PHPUnit 3.5</title>
    <link>http://sebastian-bergmann.de/archives/877-CRAP-in-PHPUnit-3.5.html</link>
            <category>New Features</category>
    
    <comments>http://sebastian-bergmann.de/archives/877-CRAP-in-PHPUnit-3.5.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=877</wfw:comment>

    <slash:comments>6</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=877</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;For the upcoming &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit 3.5&lt;/a&gt;, I have factored out all code that is related to &lt;a href=&quot;http://en.wikipedia.org/wiki/Code_coverage&quot;&gt;code coverage&lt;/a&gt; and put it into a separate component: &lt;a href=&quot;http://github.com/sebastianbergmann/php-code-coverage&quot;&gt;PHP_CodeCoverage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;PHP_CodeCoverage is a component that provides collection, processing, and rendering functionality for PHP code coverage information. It makes PHPUnit&#039;s mature code coverage functionality available outside of PHPUnit.&lt;/p&gt;

&lt;p&gt;Having all code that deals with code coverage in a separate component allows for easier development and better testing. The first result of these improved development conditions is a small new feature that I recently implemented, the support for the &lt;acronym title=&quot;Change Risk Analysis and Predictions&quot;&gt;CRAP&lt;/acronym&gt; metric.&lt;/p&gt;

&lt;p&gt;From &lt;a href=&quot;http://www.crap4j.org/&quot;&gt;crap4j.org&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The CRAP (Change Risk Analysis and Predictions) software metric [has] a mildly offensive metric name [and helps] to help protect you from truly offensive code.&lt;/p&gt;
&lt;p&gt;The CRAP metric combines &lt;a href=&quot;http://en.wikipedia.org/wiki/Cyclomatic_complexity&quot;&gt;cyclomatic complexity&lt;/a&gt; and code coverage from automated tests (e.g. [PHPUnit] tests) to help you identify code that might be particularly difficult to understand, test, or maintain &amp;mdash; the kind of code that makes developers say: This is crap! or, if they are stuck maintaining it, Oh, crap!.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The screenshot below shows how the CRAP metric is reported in the HTML code coverage report:&lt;/p&gt;

&lt;a href=&quot;http://sebastian-bergmann.de/uploads/crap.png&quot;&gt;&lt;img alt=&quot;Code Coverage Report&quot; border=&quot;0&quot; src=&quot;http://sebastian-bergmann.de/uploads/crap-highlight.png&quot;/&gt;&lt;/a&gt; 
    </content:encoded>

    <pubDate>Tue, 12 Jan 2010 10:30:00 +0100</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/877-guid.html</guid>
    <category>code coverage</category>
<category>PHP</category>
<category>PHP_CodeCoverage</category>

</item>
<item>
    <title>PHPUnit Development Moved to GitHub</title>
    <link>http://sebastian-bergmann.de/archives/876-PHPUnit-Development-Moved-to-GitHub.html</link>
            <category>Announcements</category>
    
    <comments>http://sebastian-bergmann.de/archives/876-PHPUnit-Development-Moved-to-GitHub.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=876</wfw:comment>

    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=876</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;Over the Christmas holidays I took a break from translating and editing the
&lt;a href=&quot;http://phpqabook.com/&quot;&gt;book on quality assurance in PHP projects&lt;/a&gt;
that I am working on to finally migrate the code repository of
&lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt; from a self-hosted
&lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;Subversion&lt;/a&gt; repository to a
&lt;a href=&quot;http://git-scm.com/&quot;&gt;Git&lt;/a&gt; repository that is hosted on
&lt;a href=&quot;http://github.com/&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;How did I get here?&lt;/h3&gt;

&lt;p&gt;I was staying at &lt;a href=&quot;http://openquery.com/&quot;&gt;Arjen&lt;/a&gt;&#039;s place in Brisbane
in August 2008 and one day we talked about distributed version control. Although I
knew the basic concepts behind it, I was not yet convinced enough to take the
plunge and try it out. Our discussion changed that, but it was not until my
second trip to Australia later that year that I took the initial code for
PHP_ObjectFreezer (which I had on my laptop since I started to hack on it
together with &lt;a href=&quot;http://www.priebsch.de/&quot;&gt;Stefan&lt;/a&gt; on the flight to
Atlanta for php|works 2008) and put it into a
&lt;a href=&quot;http://bazaar.canonical.com/en/&quot;&gt;bzr&lt;/a&gt; repository on
&lt;a href=&quot;http://launchpad.net/&quot;&gt;Launchpad&lt;/a&gt;. I grew comfortable enough with
bzr quickly, but never really warmed up to Launchpad.&lt;/p&gt;

&lt;p&gt;Around that time, I was hearing more and more positive things about Git and
GitHub from my peers. So I took the PHP_ObjectFreezer code base and migrated it
to Git and hosted the repository and GitHub to experiment with both the tool and
the platform. It was a step that I did not regret and all the projects that I
started since then are hosted on GitHub:
&lt;a href=&quot;http://github.com/sebastianbergmann/bytekit-cli&quot;&gt;bytekit-cli&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/phpcpd&quot;&gt;phpcpd&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/phpdcd&quot;&gt;phpdcd&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/phploc&quot;&gt;phploc&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-code-coverage&quot;&gt;PHP_CodeCoverage&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-file-iterator&quot;&gt;PHP_FileIterator&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-object-freezer&quot;&gt;PHP_ObjectFreezer&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-text-template&quot;&gt;Text_Template&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-token-stream&quot;&gt;PHP_TokenStream&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Why did I do this?&lt;/h3&gt;

&lt;p&gt;Let me start with a quote from GitHub.com:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;&lt;li&gt;Git is a fast, efficient, distributed version control system ideal for the collaborative development of software.&lt;/li&gt;
&lt;li&gt;GitHub is the easiest (and prettiest) way to participate in that collaboration: fork projects, send pull requests, monitor development, all with ease.&lt;/li&gt;&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Over the last year, I have come to appreciate Git and GitHub a lot and also
wanted to use them for PHPUnit.&lt;/p&gt;&lt;p&gt;Sure, I could have used &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/git-svn.html&quot;&gt;git-svn&lt;/a&gt;
for bi-directional operation between the existing Subversion repository and Git,
but this would have always felt like only going half the way.&lt;/p&gt;&lt;p&gt;The arguments in
favour of distributed version control systems are discussed by others far better
than I could discuss them here, so I will just quote Ian Clatworthy&#039;s
&lt;a href=&quot;http://ianclatworthy.files.wordpress.com/2007/10/dvcs-why-and-how3.pdf&quot;&gt;paper on distributed version control systems&lt;/a&gt;,
in which discusses not only the technical differences between traditional
version control systems and distributed version control systems, but also the
differences with regard to development workflows and developer interaction:&lt;/p&gt;
&lt;blockquote&gt;&lt;ul&gt;&lt;li&gt;Developers can collaborate directly without needing central
authority or incurring central administration overhead&lt;/li&gt;&lt;li&gt;Developers can
still be productive when the umbilical cord to their central VCS repository is
broken, e.g. when travelling.&lt;/li&gt;&lt;li&gt;Creating and destroying branches are
simple operations. This is particularly useful when experimenting with new
ideas, e.g. a &lt;i&gt;spike&lt;/i&gt; when using &lt;a href=&quot;http://en.wikipedia.org/wiki/Extreme_Programming&quot;&gt;eXtreme Programming&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Ad-hoc collaboration with peers [is facilitated by] intelligent merge
tracking [because] merging early and merging often is both possible and
surprisingly unpainful. It is difficult to explain just how much of an impact
this can make on how co-developers can work together more easily, e.g. when
&lt;a href=&quot;http://en.wikipedia.org/wiki/Pair_Programming&quot;&gt;Pair Programming&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;

&lt;h3&gt;What does this mean for you?&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://github.com/sebastianbergmann/phpunit&quot;&gt;PHPUnit is now hosted
on GitHub.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a nutshell, this means that the development of PHPUnit is now more open
than it was before. If you want to contribute, you just need to
&lt;a href=&quot;http://help.github.com/forking/&quot;&gt;fork&lt;/a&gt; PHPUnit on GitHub and create
a &lt;a href=&quot;http://progit.org/book/ch3-4.html&quot;&gt;topic branch&lt;/a&gt; for your
contribution. Then let me know about your topic branch and I may or may not
merge it.&lt;/p&gt;

&lt;p&gt;If you are currently using &lt;a href=&quot;http://svnbook.red-bean.com/en/1.5/svn.advanced.externals.html&quot;&gt;svn:externals&lt;/a&gt;
to pull PHPUnit into your own Subversion repository, you need to think about an
alternative as PHPUnit&#039;s Subversion repository is no longer updated and will
eventually go away.&lt;/p&gt;

&lt;h3&gt;How did I do it?&lt;/h3&gt;

&lt;p&gt;As this might be of interest to someone who wants to migrate his/her repository
from Subversion to Git, here is how I performed the migration.&lt;/p&gt;

&lt;p&gt;I started by creating a local mirror of the Subversion repository:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;# Fetch Subversion repository
svnadmin create phpunit.svn
 
cat &lt;&lt;&#039;EOF&#039; &gt; phpunit.svn/hooks/pre-revprop-change
#!/bin/sh
USER=&quot;$3&quot;
 
if [ &quot;$USER&quot; = &quot;svnsync&quot; ]; then exit 0; fi
 
echo &quot;Only the svnsync user can change revprops&quot; &gt;&amp;2
exit 1
EOF
 
chmod +x phpunit.svn/hooks/pre-revprop-change
 
svnsync init \
  --username svnsync \
  file://`pwd`/phpunit.svn \
  svn://svn.phpunit.de/phpunit
 
svnsync sync \
  --username svnsync \
  file://`pwd`/phpunit.svn&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;Then I used &lt;a href=&quot;http://github.com/nirvdrum/svn2git&quot;&gt;svn2git&lt;/a&gt; for the
actual migration:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;# Create directory for Git repository
mkdir phpunit.git &amp;&amp;amp; cd phpunit.git
 
# Use svn2git to import repository
svn2git \
  --trunk trunk \
  --branches branches/release \
  --tags tags \
  --authors /home/sb/authors.txt \
  file:///home/sb/phpunit.svn/phpunit&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;After that I had to delete quite a few superfluous branches and tags, but that
quickly dealt with. The final step was to create common ancestors for the &lt;tt&gt;master&lt;/tt&gt;, &lt;tt&gt;3.5&lt;/tt&gt;, and &lt;tt&gt;3.4&lt;/tt&gt; branches so that merging becomes easy and painless.&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;# Create 3.5 and 3.4 branches (in local repository)
git checkout remotes/origin/3.5 -b 3.5
git checkout remotes/origin/3.4 -b 3.4

# Create common ancestors for the master, 3.5, and 3.4 branches
git checkout 3.5 &amp;&amp;amp; git merge --strategy=ours master
git checkout 3.4 &amp;&amp;amp; git merge --strategy=ours 3.5

git checkout master &amp;&amp;amp; git merge --strategy=ours 3.5
git checkout 3.5 &amp;&amp;amp; git merge --strategy=ours 3.4&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;After that I had to delete quite a few superfluous branches and tags, but that
quickly dealt with.&lt;/p&gt;

&lt;p&gt;At this point I would like to thank &lt;a href=&quot;http://blog.experimentalworks.net/&quot;&gt;David Soria Parra&lt;/a&gt;
who helped me figure out some details here and there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; GitHub now supports Subversion clients:&lt;/p&gt;&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;svn co https://svn.github.com/sebastianbergmann/phpunit&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt; 
    </content:encoded>

    <pubDate>Sat, 26 Dec 2009 11:45:00 +0100</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/876-guid.html</guid>
    <category>git</category>
<category>github</category>
<category>phpunit</category>

</item>
<item>
    <title>PHPUnit 3.4.2</title>
    <link>http://sebastian-bergmann.de/archives/875-PHPUnit-3.4.2.html</link>
            <category>Announcements</category>
    
    <comments>http://sebastian-bergmann.de/archives/875-PHPUnit-3.4.2.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=875</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=875</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;I have released &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit 3.4.2&lt;/a&gt; today.&lt;/p&gt;&lt;p&gt;Besides the usual bug fixes, this release disables the backup and restore operations for static attributes (that was introduced in PHPUnit 3.4.0) by default.&lt;/p&gt;&lt;p&gt;The previous default setting caused too many problems with existing test suites (problems that would have been recognized earlier had users actually tested the PHPUnit 3.4 release candidates).&lt;/p&gt;&lt;p&gt;To enable the backup and restore operations for static attributes, simply pass the &lt;code&gt;--static-backup&lt;/code&gt; command-line switch, use the &lt;a href=&quot;http://www.phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.backupStaticAttributes&quot;&gt;&lt;code&gt;@backupStaticAttributes&lt;/code&gt;&lt;/a&gt; annotation, or the &lt;a href=&quot;http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.phpunit&quot;&gt;XML configuration file&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Below is the full list of changes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/889&quot; title=&quot;enhancement: --skeleton-class flag doesn&#039;t work with @depends annotation (closed: fixed)&quot;&gt;#889&lt;/a&gt;: &lt;tt&gt;--skeleton-class&lt;/tt&gt; does not work with &lt;tt&gt;@depends&lt;/tt&gt; annotation. &lt;a href=&quot;http://www.phpunit.de/changeset/5270&quot; title=&quot;- Merge [5263:5265] and [5269].&quot;&gt;[5270]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/902&quot; title=&quot;defect: --log-metrics throws Exception on namespaced code (closed: fixed)&quot;&gt;#902&lt;/a&gt;: &lt;tt&gt;PHPUnit_Util_File::getClassesInFile()&lt;/tt&gt; does not handle nested namespaces correctly. &lt;a href=&quot;http://www.phpunit.de/changeset/5272&quot; title=&quot;- Merge [5271].&quot;&gt;[5272]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/905&quot; title=&quot;defect: Files with no methods or classes show incorrect code coverage with ... (closed: fixed)&quot;&gt;#905&lt;/a&gt;: Files with no methods or classes show incorrect code coverage with &lt;tt&gt;--coverage-clover&lt;/tt&gt;. &lt;a href=&quot;http://www.phpunit.de/changeset/5276&quot; title=&quot;- Merge [5275].&quot;&gt;[5276]&lt;/a&gt; &lt;a href=&quot;http://www.phpunit.de/changeset/5284&quot; title=&quot;- Merge [5283].&quot;&gt;[5284]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/909&quot; title=&quot;defect: Stubbing a web service with getMockFromWsdl throws a fatal error. (closed: fixed)&quot;&gt;#909&lt;/a&gt;: Stubbing a web service with &lt;tt&gt;getMockFromWsdl()&lt;/tt&gt; throws a fatal error. &lt;a href=&quot;http://www.phpunit.de/changeset/5281&quot; title=&quot;- Merge [5280].&quot;&gt;[5281]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/918&quot; title=&quot;defect: Truncate operation throws an error (closed: fixed)&quot;&gt;#918&lt;/a&gt;: Truncate operation throws an error. &lt;a href=&quot;http://www.phpunit.de/changeset/5286&quot; title=&quot;- Merge [5285].&quot;&gt;[5286]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The backup and restore operations for static attributes has been disabled by default. &lt;a href=&quot;http://www.phpunit.de/changeset/5288&quot; title=&quot;- Partially merge [5287].&quot;&gt;[5288]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; 
    </content:encoded>

    <pubDate>Sun, 25 Oct 2009 15:55:00 +0100</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/875-guid.html</guid>
    <category>phpunit</category>
<category>release announcement</category>

</item>
<item>
    <title>PHPUnit 3.4.0</title>
    <link>http://sebastian-bergmann.de/archives/873-PHPUnit-3.4.0.html</link>
            <category>Announcements</category>
    
    <comments>http://sebastian-bergmann.de/archives/873-PHPUnit-3.4.0.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=873</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=873</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;A year and a day has passed since the release of PHPUnit 3.3. Time to finally release &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;PHPUnit 3.4&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Among the features introduced in this new version, the most notable are the support for &lt;a href=&quot;http://sebastian-bergmann.de/archives/826-Test-Dependencies-in-PHPUnit-3.4.html&quot;&gt;test dependencies&lt;/a&gt; and &lt;a href=&quot;http://sebastian-bergmann.de/archives/848-Fixture-Reuse-in-PHPUnit-3.4.html&quot;&gt;fixture reuse&lt;/a&gt; as well as the possibility to run tests in separate PHP processes for increased test isolation. Please have a look at the &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;ChangeLog&lt;/a&gt; for a complete list of changes.&lt;/p&gt;&lt;p&gt;Work on PHPUnit 3.5 has already started: the &lt;a href=&quot;http://github.com/sebastianbergmann/php-code-coverage&quot;&gt;php-code-coverage&lt;/a&gt; project on GitHub is home to a refactoring of PHPUnit&#039;s code coverage functionality that will be one of the &quot;hallmark features&quot; of PHPUnit 3.5. It will also make PHPUnit&#039;s code coverage functionality available outside the scope of PHPUnit.&lt;/p&gt; 
    </content:encoded>

    <pubDate>Wed, 16 Sep 2009 17:55:00 +0200</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/873-guid.html</guid>
    <category>phpunit</category>
<category>release announcement</category>

</item>
<item>
    <title>PHPUnit 3.4.0RC1</title>
    <link>http://sebastian-bergmann.de/archives/872-PHPUnit-3.4.0RC1.html</link>
            <category>Announcements</category>
    
    <comments>http://sebastian-bergmann.de/archives/872-PHPUnit-3.4.0RC1.html#comments</comments>
    <wfw:comment>http://sebastian-bergmann.de/wfwcomment.php?cid=872</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://sebastian-bergmann.de/rss.php?version=2.0&amp;type=comments&amp;cid=872</wfw:commentRss>
    

    <author>nospam@example.com (Sebastian Bergmann)</author>
    <content:encoded>
    &lt;p&gt;The first release candidate of &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;PHPUnit 3.4&lt;/a&gt; is now available.&lt;/p&gt;

&lt;p&gt;Among the many new features introduced in this new version, the most notable are the support for &lt;a href=&quot;http://sebastian-bergmann.de/archives/826-Test-Dependencies-in-PHPUnit-3.4.html&quot;&gt;test dependencies&lt;/a&gt; and &lt;a href=&quot;http://sebastian-bergmann.de/archives/848-Fixture-Reuse-in-PHPUnit-3.4.html&quot;&gt;fixture reuse&lt;/a&gt; as well as the possibility to run tests in separate PHP processes for increased test isolation. Please have a look at the &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;ChangeLog&lt;/a&gt; for a complete list of changes.&lt;/p&gt;

&lt;p&gt;You can help make PHPUnit 3.4 a &quot;good release&quot; by running your test suites with it and report any problems or regressions that you may encounter. You help is much appreciated!&lt;/p&gt; 
    </content:encoded>

    <pubDate>Tue, 18 Aug 2009 12:30:00 +0200</pubDate>
    <guid isPermaLink="false">http://sebastian-bergmann.de/archives/872-guid.html</guid>
    <category>phpunit</category>
<category>release announcement</category>

</item>

</channel>
</rss>