开发者

Zend Framework: How should I unit test my Mapper in Zend_Db?

How would I test my mappers in Zend_Db? Each of my model will have 3 classes:

  • The Model
  • The Mapper
  • The DbTable

Here is my Unit Test:

<?php
// Call Model_BugTest::main() if this source file is executed directly.
if (!defined("PHPUnit_MAIN_METHOD")) {
    define("PHPUnit_MAIN_METHOD", "Model_ArtistTest::main");
}

require_once dirname(__FILE__) . '/../../TestHelper.php';

/** Model_Artist */
require_once 'Artist.php';


/**
 * Test class for Model_Artist.
 *
 * @group Models
 */
class Model_ArtistTest extends PHPUnit_Framework_TestCase 
{
    /**
     * Runs the test methods of this class.
     *
     * @return void
     */
    public static function main()
    {
        $suite  = new PHPUnit_Framework_TestSuite("Model_ArtistTest");
        $result = PHPUnit_TextUI_TestRunner::run($suite);
    }

    /**
     * Sets up the fixture, for example, open a network connection.
     * This method is called before a test is executed.
     *
     * @return void
     */
    public function setUp()
    {
        $this->model = new Ly_Model_Artist();
    }

    /**
     * Tears down the fixture, for example, close a network connection.
     * This method is called after a test is executed.
     *
     * @return void
     */
    public function tearDown()
    {
    }

    public function testCanDoTest()
    {
        $this->assertTrue(true);
    }

    public function testCanFindArtist()
    {
        $artist = "Rage Against the Machine";
        $result = $this->model->findbyalpha($artist);
        var_dump($result);
    }
}

I am using Matthew's TestHelper: http://github.com/weierophinney/bugapp/blob/master/tests/TestHelper.php

The error I get is this:

c:\xampp\htdocs\ly\tests>phpunit --configuration phpunit.xml
PHPUnit 3.4.10 by Sebastian Bergmann.

.
Fatal error: Class 'Ly_Model_ArtistMapper' not found in C:\xampp\htdocs\ly\appli
cation\models\Artist.php on line 72

Seems like the Mapper is not being read. Can anyone show me how to do this kind of testing? I am new to UnitTesting and I am just starting to learn it.

This is my Artist Model

<?php
/**
 * Artist Model
 */
class Ly_Model_Artist
{
    protected $_id; //a field
    protected $_name; //a field

protected $_mapper;

    public function __construct(array $options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        }
    }

    public function __set($name, $value)
    {
        $pieces = explode('_', $name);
        foreach($pieces AS $key => $row) {
            $pieces[$key] = ucfirst($row);
        }

        $name = implode('',$pieces);
        $method = 'get' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid group property');
        }

        $this->$method($value);
    }

    public function __get($name)
    {
        $pieces = explode('_', $name);
        foreach($pieces AS $key => $row) {
            $pieces[$key] = ucfirst($row);
        }
        $name = implode('',$pieces);
        $method = 'get' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid group property');
        }

        return $this->$method();
    }

    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }
        return $this;
    }


    public function setMapper($mapper)
    {
        $this->_mapper = $mapper;
        return $this;
    }

    public function getMapper()
    {
        if (null === $this->_mapper) {
            $this->setMapper(new Ly_Model_ArtistMapper());
        }
        return $this->_mapper;
    }

    public function setId($id)
    {
        $this->_id = (int) $id;
        return $this;
    }

    public function getId()
    {
        return $this->_id;
    }

    public function setName($text)
    {
        $this->_name = (string) $text;
        return $this;
    }

    public function getName()
    {
        return $this->_name;
    }

    public function find($id)
    {
        $this->getMapper()->find($id, $this);
        return $this;
    }

    public function findbyalpha($keyword)
    {
        return $this->getMapper()->findbyalpha($keyword);
    }
}

This is the Artist Mapper:

<?php
/**
 * Artist Model Mapper
 */
class Ly_Model_ArtistMapper
{
    protec开发者_高级运维ted $_dbTable;

    public function setDbTable($dbTable)
    {
        if (is_string($dbTable)) {
            $dbTable = new $dbTable();
        }
        if (!$dbTable instanceof Zend_Db_Table_Abstract) {
            throw new Exception('Invalid table data gateway provided');
        }
        $this->_dbTable = $dbTable;
        return $this;
    }

    public function getDbTable()
    {
        if (null === $this->_dbTable) {
            $this->setDbTable('Ly_Model_DbTable_Artist');
        }
        return $this->_dbTable->getAdapter();
    }


    public function find($id, Ly_Model_Artist $artist)
    {
        if(!isset($id) OR empty($id)) {
            throw new Exception ('Could not find id.');
        }

        $result = $this->getDbTable()->find($id);
        if (0 == count($result)) {
            return;
        }
        $row = $result->current();
        $artist->setId($row->id)
               ->setName($row->name);
    }

    public function findbyalpha($keyword)
    {
        if(!isset($keyword) OR empty($keyword)) {
            throw new Exception ('Could not find keyword.');
        }

        $keyword = $this->getDbTable()->quote($keyword.'%');

        //$sql = $this->getDbTable()->select()->where('twitter_id = ?',$twitter_id)->order('weight');
        $sql = "SELECT
                DISTINCT
                a.name
                FROM artist a
                WHERE a.name LIKE ".$keyword."
                ORDER BY a.name ASC
                ";

        //Zend_Debug::dump($sql);
        $result =  $this->getDbTable()->fetchAll($sql);
        return $result;
    }
}

And the Db_Table just looks like this:

<?php
class Ly_Model_DbTable_Artist extends Zend_Db_Table_Abstract
{
    protected $_name = 'artist';
}


Change the mapper to use the Inversion of Control pattern (insert the DB Table Object into the constructor (at least optionally) that way you can disconnect it and pass in a mock/stub object.


You should test your models (which call your mapper). That way, you will know if something is wrong with your mappers.

Have you tried in your Artists model setting the mapper method like

public function setMapper(Ly_Model_ArtistMapper $mapper) { ... }


Unit tests are meant to test a small amount of work, i.e. a method. Everything that the method depends on should be mocked/stubbed (success/failure) out as that will be tested else where in another unit test.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜