Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating mock Objects in PHP unit

I've searched but can't quite find what I'm looking for and the manual isn't much help in this respect. I'm fairly new to unit testing, so not sure if I'm on the right track at all. Anyway, onto the question. I have a class:

<?php
    class testClass {
        public function doSomething($array_of_stuff) {
            return AnotherClass::returnRandomElement($array_of_stuff);
        }
    }
?>

Now, clearly I want the AnotherClass::returnRandomElement($array_of_stuff); to return the same thing every time. My question is, in my unit test, how do I mockup this object?

I've tried adding the AnotherClass to the top of the test file, but when I want to test AnotherClass I get the "Cannot redeclare class" error.

I think I understand factory classes, but I'm not sure how I would apply that in this instance. Would I need to write an entirely seperate AnotherClass class which contained test data and then use the Factory class to load that instead of the real AnotherClass? Or is using the Factory pattern just a red herring.

I tried this:

    $RedirectUtils_stub = $this->getMockForAbstractClass('RedirectUtils');

    $o1 = new stdClass();
    $o1->id = 2;
    $o1->test_id = 2;
    $o1->weight = 60;
    $o1->data = "http://www.google.com/?ffdfd=fdfdfdfd?route=1";
    $RedirectUtils_stub->expects($this->any())
         ->method('chooseRandomRoot')
         ->will($this->returnValue($o1));
    $RedirectUtils_stub->expects($this->any())
         ->method('decodeQueryString')
         ->will($this->returnValue(array()));

in the setUp() function, but these stubs are ignored and I can't work out whether it's something I'm doing wrong, or the way I'm accessing the AnotherClass methods.

Help! This is driving me nuts.

like image 372
Mike Avatar asked Aug 12 '09 16:08

Mike


1 Answers

With Unit Tests you want to create 'test' classes that contain static data, and then pass those into your tested class. This removes variables from the testing.

class Factory{
    function build()
    {
        $reader = new reader();
        $test = new test($reader);
        // ..... do stuff
    }

}

class Factory{
    function build()
    {
        $reader = new reader_mock();
        $test = new test($reader);
        // ..... do stuff
    }

}
class reader_mock
{
    function doStuff()
    {
        return true;
    }
}

Because you are using Static Classes, you would have to remove AnotherClass from the program, and then recreate it so that it only contains functions that return test data. Normally though, you, don't want to actually remove classes from the program, which is why you pass classes in like the above example.

like image 56
Tyler Carter Avatar answered Oct 13 '22 04:10

Tyler Carter