4

I have an interface I want to mock, and mock the behaviour of one of it's methods.

So I have created a callback that mocks the behaviour very simply.

This test passes if I create a new object that is based on this interface, but I would like to mock the interface.

The mocked setUp method is being called fine, and calling getVar('testing') in my callback returns the value. However my assertion fails, because that value isn't available.

It seems that you can't do this in PHPUnit? Unless I am being stupid.

Brief explanation of the code flow; The code in "getVar" calls a method which calls the "setUp" on the added plugin. When it calls "setUp" it passes in "$this". It is $this I am expecting to be passed by reference and which works with a "real" object.

class DefaultRendererTest extends \PHPUnit_Framework_TestCase
{

    public function testSetGetVar()
    {
        $theme = $this->getMock('ThemeInterface');

        $plugin = $this->getMock('PluginInterface');
        $plugin->expects($this->once())
          ->method('setUp')
          ->will($this->returnCallback(function($r){

              $r->setVar('testing', "fooBar");

        }));

        $renderer = new DefaultRenderer($theme, null);
        $renderer->addPlugin($plugin);
        $this->assertEquals('fooBar',$renderer->getVar('testing'));
    }
}

For info here is the interface, the DefaultRenderer implements a RendererInterface

interface PluginInterface
{
    function setUp(RendererInterface $renderer);
}
johnwards
  • 1,901
  • 3
  • 18
  • 27
  • Looks perfectly valid to me. Did you check if $r and $renderer are actually references to the same object? Though, I don't see a reason why they shouldn't. Maybe there is a bug in setVar() or getVar()? – tobyS Mar 02 '11 at 17:11

1 Answers1

4

OK, out of interest, I tracked down the issue. It seems that PHPUnit automatically clones the parameters before the actual invocation takes place. I don't see a real reason for this, but maybe there is one. Taking a look at Framework/MockObject/Invocation/Static.php, there is only a single way how you can avoid this (on basis of the built in mock code): Implement a private __clone() method in the DefaultRenderer.

I'd also suggest you ask on IRC or the PHPUnit mailinglist about this behaviour or the mock object library.

tobyS
  • 860
  • 1
  • 7
  • 15
  • 3
    Sebastian has already said he's not sure if this is the correct behavior but hasn't made a final decision one way or the other. It would help to provide feedback that cloning is the wrong behavior. – David Harkness Mar 02 '11 at 19:46
  • 1
    _(related)_ (To add to Davids correct comment): I've had the same issue/question and asked sebastian about it: http://stackoverflow.com/questions/4702132/problem-with-returncallback-of-phpunit-mocks/4711782#4711782 – edorian Mar 03 '11 at 08:56