Question

I am not sure if I am doing something wrong or it is a bug with PHPUnit and mock objects. Basically I am trying to test if $Model->doSomething() is called when $Model->start() is triggered.

I am using Ubuntu in a VirtualBox, and phpunit 1.1.1 installed via pear.

The full code is below. Any help would be appreciated, it's driving me crazy.

<?php
require_once 'PHPUnit/Autoload.php';

class Model
{
    function doSomething( ) {
        echo 'Hello World';
    }

    function doNothing( ) { }

    function start( ) {
        $this->doNothing();
        $this->doSomething();
    }
}

class ModelTest extends PHPUnit_Framework_TestCase
{
    function testDoSomething( )
    {
        $Model = $this->getMock('Model');
        $Model->expects($this->once())->method('start'); # This works
        $Model->expects($this->once())->method('doSomething'); # This does not work
        $Model->start();
    }
}
?>

The output from PHPUnit:

There was 1 failure:

1) ModelTest::testDoSomething
Expectation failed for method name is equal to <string:doSomething> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.


FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
Était-ce utile?

La solution

As you found, you need to tell PHPUnit which methods to mock. Also, I would avoid creating expectations for methods that you are calling directly from the test. I would write the above test like this:

function testDoSomething( )
{
    $Model = $this->getMock('Model', array('doSomething');
    $Model->expects($this->once())->method('doSomething');
    $Model->start();
}

Autres conseils

Just to expand on why David Harkness's answer works, if you do not specify the $methods parameter to getMock then all functions in the class are mocked. Incidentally, you can confirm this with:

class ModelTest extends PHPUnit_Framework_TestCase
{
    function testDoSomething( )
    {
        $obj = $this->getMock('Model');
        echo new ReflectionClass(get_class($obj));
        ...
    }
}

So, why does it fail? Because your start() function has been mocked too! I.e. the function body you have given has been replaced, and so your $this->doSomething(); line never gets run.

Hence, when there are any functions in your class that you need to be preserved, you'll have to explicitly give the list of all other functions.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top