expectOnce() on a static method?

Discussion of testing theory and practice, including methodologies (such as TDD, BDD, DDD, Agile, XP) and software - anything to do with testing goes here. (Formerly "The Testing Side of Development")

Moderator: General Moderators

Post Reply
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

expectOnce() on a static method?

Post 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.
phait
Forum Commoner
Posts: 46
Joined: Wed Apr 07, 2004 4:41 am
Location: watford / leicester, UK

Post 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.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post 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.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post 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.
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post 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')"
Post Reply