Question

My problem is, that I need to list every call to a mock object, because I need to check them. I haven't find anything about this feature in SimpleTest documentation. :S

Maybe there is another way to test my code:

class Clean_Collection_Tree_NestedArrayParser {

    protected $path = array();
    protected $depth = -1;

    /** @var Clean_Collection_Tree_MapTreeInterface */
    protected $tree;

    public function setBasePath(array $path) {
        $this->path = $path;
    }

    public function setTree(Clean_Collection_Tree_MapTreeInterface $tree) {
        $this->tree = $tree;
    }

    public function parse($subject) {
        $this->parseArray($subject);
    }

    public function parseArray(array $array) {
        ++$this->depth;
        foreach ($array as $key => $value) {
            $this->path[$this->depth] = $key;
            if (is_array($value)) {
                $this->tree->put($this->path, new Clean_Collection_Map_Map());
                $this->parseArray($value);
            } else
                $this->tree->put($this->path, $value);
        }
        if (!empty($array))
            array_pop($this->path);
        --$this->depth;
    }

}

This is a parser waiting for a nested array from which I intend to create a Map object Tree. I inject the actual tree with setTree(Clean_Collection_Tree_MapTreeInterface $tree) and the map tree interface is:

interface Clean_Collection_Tree_MapTreeInterface extends Clean_Collection_CollectionInterface {

    public function putAll(array $array);

    public function put(array $path, $value);

    public function get(array $path);

    public function getAll(array $pathes);

    public function removeAll(array $pathes);

    public function remove(array $path);

    public function contains(array $path);
}

The parser uses only the put(array $path, $value) method. So listing every called put method will show me what went wrong in the parser. (If the SimpleMock does not have this feature I can create my own mock object which us implementing the interface. I'm on it.)

Was it helpful?

Solution

The problem is in the SimpleMock class design:

protected function addCall($method, $args) {

    if (! isset($this->call_counts[$method])) {
        $this->call_counts[$method] = 0;
    }
    $this->call_counts[$method]++;
}

They should have created a logger class for logging call properties instead of setting a property in the SimpleMock ... We can create a workaround by extending the SimpleMock class:

class LoggedMock extends SimpleMock {

    protected $invokes = array();

    public function &invoke($method, $args) {
        $this->invokes[] = array($method, $args);
        return parent::invoke($method, $args);
    }

    public function getMockInvokes() {
        return $this->invokes;
    }

}

and set it as base mock class:

    require_once __DIR__.'simpletest/autorun.php';
    SimpleTest::setMockBaseClass('LoggedMock');

After that we can get the invoke list with the $mockObj->getMockInvokes().

Edit: we cannot extend the addCall, because in the first line of the invoke method the method name is converted to lowerCase, so by extending the addCall we can only log the lowerCase format, and not the camelCase. (I think that lower case converting is a mistake...)

I created a test for demonstration:

interface Nike {

    public function justDoIt();
}

class NikeUser {

    protected $nike;

    public function setNike(Nike $nike) {
        $this->nike = $nike;
    }

    public function doIt() {
        $this->nike->justDoIt();
    }

}

Mock::generate('Nike', 'MockNike');

class NikeUserTest extends UnitTestCase {

    public function testDoItButWeDontWantJustDoIt() {
        $mockNike = new MockNike();

        $nikeUser = new NikeUser();
        $nikeUser->setNike($mockNike);

        $expectedInvokes = array();

        $nikeUser->doIt();
        $expectedInvokes[] = array('justDoIt', array());
        $this->assertEqual($expectedInvokes, $mockNike->getMockInvokes());
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top