3

Possible Duplicate:
PHP - override existing function

I want to use mocking to unit test some of my functions that have external dependencies.

So here goes... Below is a simplified model of what I'm working with. A lot of the code I have inherited is written in this way, so I would like to be able to write some simple tests without having to rewrite if possible:

function display_tasks($id)
{
    $tasks = call_some_function_that_runs_a_database_query($id);

    $html = "<some html>";

    foreach ($tasks as $task)
    {
        // Some operations here
    }

    $html .= "</some html>";

    return $html;
}

The code that my function is calling is not wrapped in an object, so I am having trouble putting the various examples into practice, as 99% of the examples on the internet are based on object-oriented code. Is it even possible to mock procedural functions directly from PHPunit?

I would like to be able to mock out whatever call_some_function_that_runs_a_database_query is returning. I have had a go at using the built-in PHPunit mocking methods, but doing this doesn't override the result from the original call in my function.

Any help or examples would be really appreciated.

Community
  • 1
  • 1
nonshatter
  • 3,347
  • 6
  • 23
  • 27

1 Answers1

3

You can use the runkit PHP extension to replace a function with one that will return what you want during the test. It's more cumbersome than mocking objects because you have to take care to swap the original back in after the test under all cases (pass, fail, error).

Function Under Test

function getTasksFromDatabase($id) {
    // call to database...
}

Test Case

function stub_getTasksFromDatabase($id) {
    return array('one', 'two', 'three');
}

class getUserTest extends PHPUnit_Framework_TestCase {
    public static function setUpBeforeClass() {
        runkit_function_rename('getTasksFromDatabase', 'orig_getTasksFromDatabase');
        runkit_function_rename('stub_getTasksFromDatabase', 'getTasksFromDatabase');
    }

    public function tearDownAfterClass() {
        runkit_function_rename('getTasksFromDatabase', 'stub_getTasksFromDatabase');
        runkit_function_rename('orig_getTasksFromDatabase', 'getTasksFromDatabase');
    }

    public function setUp() {
        $html = getTasks(1);
        self::assertEquals('<some html>...one...two...three...</some html>', $html);
    }
}
David Harkness
  • 35,992
  • 10
  • 112
  • 134
  • Thanks David. I actually came across this solution late last night, but instead of installing runkit, I just installed the php test helpers (also written by the great Sebastian Bergmann). Details here: https://github.com/sebastianbergmann/php-test-helpers#renaming-functions – nonshatter Oct 25 '12 at 11:23