7

I'm going through the zend tutorials and I am testing a class with a mock object with phpunit. When I pass a mock created from Zend\Db\TableGateway to my class, who's constructor expects a Zend\Db\TableGateway, I get an type error:

"...Argument 1 passed to Album\Model\AlbumTable::__construct() must be an instance of Zend\Db\TableGateway\TableGateway, instance of Mock_TableGateway_65b55cb0 given..."

Is this supposed happen? Are phpunit mock objects supposed to be able to "fool" the class?

Here is the real class:

class AlbumTable {
    protected $tableGateway;

    public function __construct(TableGateway $tableGateway) {
        $this->tableGateway = $tableGateway;
    }

    public function fetchAll() {
        $resultSet = $this->tableGateway->select();
        return $resultSet;
    }

    public function getAlbum($id){
        $id = (int) $id;
        $rowset = $this->tableGateway->select(array('id' => $id));
        $row = $rowset->current();
        if(!$row) {
            throw new \Exception("Couldn't find row: $id");
        }
        return $row;
    }

    public function saveAlbum(Album $album) {
        $data = array(
            'artist' => $album->artist,
            'title' => $album->title,
        );

        $id = (int)$album->id;
        if ($id == 0) {
            $this->tableGateway->insert($data);
        } else {
            if ($this->getAlbum($id)) {
                $this->tableGateway->update($data, array('id' => $id));
            } else {
                throw new \Exception('Form id does not exist');
            }
        }
    }

    public function deleteAlbum($id) {
        $this->tableGateway->delete(array('id' => $id));
    }

}

and the test:

class AlbumTableTest extends PHPUnit_Framework_TestCase {
    public function testFetchAllReturnsAllAlbums() {
        $resultSet = new ResultSet();
        $mockTableGateway = $this->getMock('Zend\Db\TableGateway',
            array('select'), array(), '', false);

        $mockTableGateway->expects($this->once())
            ->method('select')
            ->with()
            ->will($this->returnValue($resultSet));

        $albumTable = new AlbumTable($mockTableGateway);
        $this->assertSame($resultSet, $albumTable->fechAll());
    }
}

and the error:

Time: 102 ms, Memory: 5.00Mb

There was 1 error:

1) AlbumTest\Model\AlbumTableTest::testFetchAllReturnsAllAlbums
Argument 1 passed to Album\Model\AlbumTable::__construct() must be an instance of Zend\Db\TableGateway\TableGateway, instance of Mock_TableGateway_65b55cb0 given, called in C:\Users\MEEE\Google Drive\code\iis\www\CommunicationApp\module\Album\test\AlbumTest\Model\AlbumTableTest.php on line 20 and defined

C:\Users\MEEE\Google Drive\code\iis\www\CommunicationApp\module\Album\src\Album\Model\AlbumTable.php:9
C:\Users\MEEE\Google Drive\code\iis\www\CommunicationApp\module\Album\test\AlbumTest\Model\AlbumTableTest.php:20

FAILURES!
Tests: 4, Assertions: 9, Errors: 1.
1
  • 1
    after creating the mock, do a var_dump to see if instanceof returns true... var_dump($mockTableGateway instanceof Zend\Db\TableGateway); Commented Feb 25, 2014 at 14:35

1 Answer 1

9

You are not mocking the correct class. You are creating a mock of a Zend\Db\TableGateway and you need to actually mock Zend\Db\TableGateway\TableGateway

Change you test code to:

    $mockTableGateway = $this->getMock('Zend\Db\TableGateway\TableGateway',
        array('select'), array(), '', false);

Your mock was failing a type-hint because your not mocking the correct class.

Mock objects will extend the class that you are mocking, so they will be an instance of the class being mocked.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.