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.
有帮助吗?

解决方案

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();
}

其他提示

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top