Bryan M. Bryan M. - 8 months ago 21
PHP Question

PHPUnit: stub methods undefined

I must be missing something. I'm trying to stub methods on a class in PHPUnit, but when I invoke the method on the mock object, it tells me that method is undefined.

Example class to stub:

namespace MyApp;

class MyStubClass
public function mrMethod()
// doing stuff

To stub it, I write:

// specifying all getMock() args to disable calling of class __construct()
$stub = $this->getMock('MyStubClass', array(), array(), 'MockMyStubClass', false, false, false);
->will($this->returnValue('doing stuff'));

But upon invoking the stubbed method, I get an exception:

//PHP Fatal error: Call to undefined method MockMyStubClass::mrMethod()

I'm using PHPUnit 3.4.3 with PHP 5.3.0.

Another small thing I noticed was that if specifying a namespace in the
method results in a class loading exception because of a double namespace:

$stub = $this->getMock('MyApp\MyStubClass');
// Fatal error: Class 'MyApp\MyApp\MyStubClass' not found

That strikes me as rather odd (and getmock() will not accept a namespace with a leading backslash). The only thing I could think to cause that would may be because this class is
registered with an autoloader?

Any thoughts?


Answering my own question:

After quite a bit of frustration, I did manage to get things working. I'm not sure precisely what the issue was, but did discover a few things that might help others:

  • Make sure you're running the latest version of PHPUnit (3.4.6 as of this writing)
  • Use the fully-qualified namespace minus the first backslash.


Part of my problem was that PHPUnit was creating a stub class WidgetFactory that was not actually stubbing MyApp\Widgets\WidgetFactory. One would expect that an exception would occur if trying to stub a non-existent class, but it doesn't seem to happen with the namespace confusion.

Also, there is a question over here that suggests using the class alias method as follows:

    class_alias('MyApp\Widgets\WidgetFactory', 'WidgetFactory');

While this did temporarily solve my problem, I would strongly advise against using it. class_alias() cannot be called twice for the same alias without raising an exception, which causes obvious problem if used in the setup() method, or as part of the stub generation.