views:

389

answers:

1

Hi,

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.

+3  A: 

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.

Chacha102
Brilliant, thanks for the response. One question though; so, I've got a my Factory class, which creates all the instances for me. This is the class that goes into production. Do I add the mock object stuff into this class, or do I just leave the main Factory Class as production, then add a new factory class for the unittests?
Mike
Thats realyl up to you. You can either make a new factory class for testing, or you can make sure that you've cleaned up your Factory class after you tested it.
Chacha102