Page 1 of 1

expectOnce() on a static method?

Posted: Wed Sep 20, 2006 5:17 pm
by Chris Corbyn
Using SimpleTest how can I do the same as I do for Mock objects and specify expectOnce() on a factory method which is called statically? It's actually not the factory method itself but something that would be called automatically based upon a certain configuration.

Generating a mock object from the class doesn't catch the static call.

Cheers,

d11 :)

EDIT | My ad-hoc way of thinking was to "cheat" and set a value to TRUE in the class if the method has executed, then I can post-check this in the test case.

Posted: Wed Sep 20, 2006 6:15 pm
by phait
if I understand you right, have you tried creating the class that contains the factory method as a partial mock and then pass in a mock object to be returned by that method. You should then be able to do an expectOnce on that method... assuming it is not private. You can have assertions against the Mock object as well, so you will know it has been called and is being used.

SimpleTest partial mocks page

It sounds similar to something I was trying to do today, so this is fresh in my mind... however, it is also still a little fuzzy so YYMV with this.

anyway, hth a little.

Posted: Wed Sep 20, 2006 6:55 pm
by Ambush Commander
Partial mock is one way to go about doing things. Either way, however, this is a code smell: your static function call is tying you to a concrete implementation of the function. Unless the static function is, itself, dynamic and able to re-route requests to different implementations/mocks (as is often done with Singletons), you really should consider eliminating it.

Posted: Thu Sep 21, 2006 12:18 am
by Chris Corbyn
~phait; I tried a partial Mock but it didn't seem to catch the call to the method unless it was called as part of the object. I'll have another go thanks.

~AC; It's a factory class that doesn't really need to be in a particular state... it's just a one-off execution but it has several functions because the way the object it's creating is instantiated may vary.

Kinda like:

Code: Select all

class MyFactory
{
    public static function getObject()
    {
        switch ($some_condition)
        {
            case 'X':
            return self::getObjectOneWay();
            case 'Y':
            return self::getObjectAnotherWay();
            case 'Z':
            // .... and you get the idea
        }
    }

    public static function getObjectOneWay() {}
    
    public static function getObjectAnotherWay() {}
}
There are some other little functions common to each sub-factory and I would like to demonstrate via tests that they actually execute.

Posted: Thu Sep 21, 2006 2:35 am
by Weirdan
Mocks don't play nicely with static methods/classes for obvious reason: unlike your class mock has to mantain its state. Since php4 doesn't allow class variables, it seems to be impossible to maintain the mock state unless it gets instantiated (which kinda defies the purpose of mocking a static class).

it could be possible to use the method like this though:

Code: Select all

// ...
   /**
    * @static
    * @access protected
    */
    function &staticMember($action, $name, &$value = null) {
        static $staticMembers = array();
        if($action == 'get') {
            return $staticMembers[$name];
        } elseif($action == 'set') {
            $staticMembers[$name] =& $value;
        }
    }
to emulate php5's 'self::$varname' on php4 like "self::staticMember('get', 'varname')"