Page 1 of 1

Expectations At Arbitrary Script-points

Posted: Sat Oct 22, 2005 7:30 pm
by Ambush Commander
Recently, I tried to run this test code on SimpleTest:

Code: Select all

$this->mapper->expectArguments('delete', array(&$captcha1));
$this->mapper->expectArguments('delete', array(&$captcha2));
So it would always inextricably fail. I later found out that both expectArguments are checked on every method call, so one would always fail on me, rather than expectArguments represent possible arguments that could be passed.

So I ended up using expectArgumentsAt(). However, the UnitOfWork doesn't apply any particular logic on which order the captcha objects are passed to the mapper (it just so turned out that captcha1 came before captcha2). Which means a brittle testcase.

If you had to have this sort of testcase, what would you do? I have a sneaking suspicion that the solution is a custom Expectation class, but I'm not sure. What would you do?

Posted: Sat Oct 22, 2005 8:42 pm
by sweatje

Code: Select all

$this->mapper->expectArgumentsAt(0, 'delete', array(&$captcha1));
$this->mapper->expectArgumentsAt(1, 'delete', array(&$captcha2));
Is really your only choice. I was bugging Marcus to have an "expectOnce" that was not alway the first one, but instead would just be happy if it was ever called, and he thought something similar might go into the rewrite of MockObjects in an upcomming version of simpletest.

Posted: Sat Oct 22, 2005 8:51 pm
by Ambush Commander
How about...

Code: Select all

class EqualsOneExpectation extends SimpleExpectation {
    
    var $validObjects = array();
    
    function test(&$obj) {
        foreach ($this->validObjects as $key => $value) { //assign by reference hack
            if ($this->validObjects[$key] === $obj) return true;
        }
        return false;
    }
    
    function add(&$obj) {
        $this->validObjects[] =& $obj;
    }
    
    function testMessage($obj) {
        return "Object [" . class_name($obj) . "] should match one of allowed objects";
    }
}

Code: Select all

$expectation =& new EqualsOneExpectation();
$expectation->add(&$captcha1);
$expectation->add(&$captcha2);
$this->mapper->expectArguments('delete',array(&$expectation));
This is what I was thinking... would it work?

Posted: Sat Oct 22, 2005 10:20 pm
by sweatje

Code: Select all

foreach ($this->validObjects as $key => $value) { //assign by reference hack
is probably better written

Code: Select all

foreach (array_keys($this->validObjects) as $key) {
Also, I think I might lean towards an InListExpectation and just pass in the valid array of cadidates to the constructor.

Posted: Sat Oct 22, 2005 10:23 pm
by Ambush Commander
Mmm... never thought of that...