[Patch] PHP 5.3 + namespaces + Mock objects

Discussion of testing theory and practice, including methodologies (such as TDD, BDD, DDD, Agile, XP) and software - anything to do with testing goes here. (Formerly "The Testing Side of Development")

Moderator: General Moderators

Post Reply
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

[Patch] PHP 5.3 + namespaces + Mock objects

Post by Chris Corbyn »

Just thought I'd share this in the interim before it gets included in subversion of simpletest.

Code: Select all

--- tests/lib/simpletest-svn/mock_objects.php   (revision 1659)
+++ tests/lib/simpletest-svn/mock_objects.php   (working copy)
@@ -1189,6 +1189,7 @@
     var $_mock_class;
     var $_mock_base;
     var $_reflection;
+    var $_namespace;
 
     /**
      *    Builds initial reflection object.
@@ -1197,6 +1198,10 @@
      *                                but no behaviour.
      */
     function MockGenerator($class, $mock_class) {
+        if (preg_match('/^(.*?)::([^:]+)$/D', $mock_class, $matches)) {
+          $mock_class = $matches[2];
+          $this->_namespace = $matches[1];
+        }
         $this->_class = $class;
         $this->_mock_class = $mock_class;
         if (! $this->_mock_class) {
@@ -1293,8 +1298,16 @@
         if (count($interfaces) > 0) {
             $implements = 'implements ' . implode(', ', $interfaces);
         }
-        $code = "class " . $this->_mock_class . " extends " . $this->_mock_base . " $implements {\n";
-        $code .= "    function " . $this->_mock_class . "() {\n";
+        $code = "";
+        if (isset($this->_namespace)) {
+          $code .= "namespace " . $this->_namespace . ";\n";
+          $code .= "use ::" . $this->_mock_base . ";\n";
+          $constructor = "__construct";
+        } else {
+          $constructor = $this->_mock_class;
+        }
+        $code .= "class " . $this->_mock_class . " extends " . $this->_mock_base . " $implements {\n";
+        $code .= "    function " . $constructor . "() {\n";
         $code .= "        \$this->" . $this->_mock_base . "();\n";
         $code .= "    }\n";
         if (in_array('__construct', $this->_reflection->getMethods())) {
@@ -1315,11 +1328,19 @@
      *    @access private
      */
     function _createSubclassCode($methods) {
-        $code  = "class " . $this->_mock_class . " extends " . $this->_class . " {\n";
+        $code = "";
+        if (isset($this->_namespace)) {
+          $code .= "namespace " . $this->_namespace . ";\n";
+          $code .= "use ::" . $this->_mock_base . ";\n";
+          $constructor = "__construct";
+        } else {
+          $constructor = $this->_mock_class;
+        }
+        $code .= "class " . $this->_mock_class . " extends " . $this->_class . " {\n";
         $code .= "    var \$_mock;\n";
         $code .= $this->_addMethodList(array_merge($methods, $this->_reflection->getMethods()));
         $code .= "\n";
-        $code .= "    function " . $this->_mock_class . "() {\n";
+        $code .= "    function " . $constructor . "() {\n";
         $code .= "        \$this->_mock = &new " . $this->_mock_base . "();\n";
         $code .= "        \$this->_mock->disableExpectationNameChecks();\n";
         $code .= "    }\n";
@@ -1341,11 +1362,19 @@
      *    @access private
      */
     function _extendClassCode($methods) {
-        $code  = "class " . $this->_mock_class . " extends " . $this->_class . " {\n";
+        $code = "";
+        if (isset($this->_namespace)) {
+          $code .= "namespace " . $this->_namespace . ";\n";
+          $code .= "use ::" . $this->_mock_base . ";\n";
+          $constructor = "__construct";
+        } else {
+          $constructor = $this->_mock_class;
+        }
+        $code  .= "class " . $this->_mock_class . " extends " . $this->_class . " {\n";
         $code .= "    var \$_mock;\n";
         $code .= $this->_addMethodList($methods);
         $code .= "\n";
-        $code .= "    function " . $this->_mock_class . "() {\n";
+        $code .= "    function " . $constructor . "() {\n";
         $code .= "        \$this->_mock = &new " . $this->_mock_base . "();\n";
         $code .= "        \$this->_mock->disableExpectationNameChecks();\n";
         $code .= "    }\n";
This allows Mock classes to be generated from/inside namespaces.

For example, if you have a class file:

Code: Select all

<?php
 
namespace Foo;
 
class Interface Bar {
  public function doSometing();
}
Then you could have a test which mocks that interface in the correct namespace.

Code: Select all

<?php
 
namespace Foo;
 
use ::Mock;
use ::UnitTestCase;
 
Mock::generate('Foo::Bar', 'Foo::MockBar');
 
class SomeTest extends UnitTestCase {
  public function testSomething() {
    $mock = new MockBar();
    $mock->expectOnce('doSomething');
    $mock->doSomething();
  }
}
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: [Patch] PHP 5.3 + namespaces + Mock objects

Post by Ambush Commander »

Have you created a unit test for this? :-D
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: [Patch] PHP 5.3 + namespaces + Mock objects

Post by Chris Corbyn »

Meh! Unit Testing is dead to me! :P :lol:

No I haven't actually... I just threw it together in 5 mins. It's not really supposed to be a "proper" implementation... just a proof of concept ;)
lastcraft
Forum Commoner
Posts: 80
Joined: Sat Jul 12, 2003 10:31 pm
Location: London

Re: [Patch] PHP 5.3 + namespaces + Mock objects

Post by lastcraft »

Hi...
Chris Corbyn wrote: No I haven't actually... I just threw it together in 5 mins.
Cheers for this :).

yours, Marcus
Post Reply