这个变量怎么没有定义?

时间:2011-05-11 10:49:24

标签: unit-testing zend-framework phpunit

我想知道如何在zend框架中测试模型,但是当我运行测试时它会给我一个错误,代码如下:

这是我要测试的模型:

<?php



class Application_Model_User extends Custom_Model_Base {
    protected $_table = 'user';
    protected $_primary = array('id');
    protected $_primary_ai = 'id';
    protected $_data = array();
    protected $_data_changed = array();
    protected $_readonly = array('id');
    static
    protected $_columns = array(
        'id',
        'login',
        'password_hash',
        'name',
        'surname',
        'gender',
        'street',
        'postal_code',
        'city',
        'mobile',
        'homephone',
        'email',
        'is_active');

    public function __construct() {
        parent::__construct();
    }

    static function create(array $data) {
        return parent::_create(
                $_table,
                get_class(),
                $data,
                self::$_columns,
                true
        );
    }

    static function load($id) {
        return self::_selectAndBind(
                get_class(),
                        self::getDefaultAdapter()
                        ->select()
                        ->from($_table)
                        ->where('id = ?', array($id)),
                true);
    }

    static function find($name, $order=null, $limit=null, $offset=null) {
        return self::_selectAndBind(
                get_class(),
                        self::getDefaultAdapter()
                        ->select()
                        ->from($_table)
                        ->where('name = ?', array($name))
                        ->order($order)
                        ->limit($limit, $offset)
        );
    }

}

它扩展了一个基类,即:

<?

abstract class Custom_Model_Base
{
    /** @var Zend_Db_Adapter_Abstract */
    static protected $_db_default = null;

    /** @var Zend_Db_Adapter_Abstract */
    protected $_db = null;
    protected $_table = '';
    protected $_primary = array();
    /** $var string indicates which column from pk using auto increment function, set to null if none column is using auto incrementation */
    protected $_primary_ai = null;
    protected $_data = array();
    protected $_data_changed = array();
    protected $_readonly = array();


    /**
     * @param Zend_Db_Adapter_Abstract $adapter overrides global (static) adapter used for all models
     */
    protected function  __construct($adapter=null) {
        if ($adapter !== null) {
            if ($adapter instanceof Zend_Db_Adapter_Abstract)
            {
                $this->_db = $adapter;
                return;
            }
            $this->_db = &self::$_db_default;
        }

    }

    /**
     * @param $default_adapter allows to set default adapter for whole model layer based on that class
     */
    static public function init($default_adapter = null)
    {
        if (self::$_db_default === null)
        {
            if (!is_null($default_adapter))
            {
                if (!$default_adapter instanceof Zend_Db_Adapter_Abstract)
                {
                    throw new Exception('Provided adapter does not extend Zend_Db_Adapter_Abstract');
                }
                self::$_db_default = $default_adapter;
            }
            else if (Zend_Registry::isRegistered('db'))
            {
                self::$_db_default = Zend_Registry::get('db');
            }
            else
            {
                throw new Exception('No default adapter provided for the model layer');
            }

        }
    }

    /**
     * @return Zend_Db_Adapter_Abstract default database adapter
     */
    static public function getDefaultAdapter()
    {
        return self::$_db_default;
    }

    /**
     * Saves changed columns from the model object
     * @return bool success - true / failure - false
     */
    public function save()
    {
        $to_update = array();
        foreach(array_keys($this->_data_changed) as $col)
        {
            $to_update[$col] = $this->_data[$col];
        }

        if (count($to_update))
        {
            // create where clause
            $where = array();
            foreach($this->_primary as $pk)
            {
                $where = array($pk.' = ?' => $this->_data[$pk]);
            }

            return ($this->_db->update($this->_table, $to_update, $where) != 0);
        }
        else
        {
            return true;
        }
    }


    public function  __set($n, $v)
    {
        if (!isset($this->_data[$n]))
        {
            throw new Exception('Column \''.$n.'\' doesn\'t exists');
        }
        else if (in_array($n, $this->_readonly))
        {
            throw new Exception('Column \''.$n.'\' is set as read-only');
        }

        if ($this->_data[$n] != $v)
        {
            $this->_data_changed[$n] = 1;
            $this->_data[$n] = $v;
        }
    }

    public function  __get($v)
    {
        if (!isset($this->_data[$n]))
        {
            throw new Exception('Column \''.$n.'\' doesn\'t exists');
        }
        return $this->_data[$n];
    }


}

我的测试代码是:

<?php

require_once(APPLICATION_PATH.'/models/CustomModelBase.php');

class Model_User2Test 
    extends PHPUnit_Framework_TestCase
{
    protected $_model;

    public function setUp() {

        parent::setUp();

        $this->_model = new Application_Model_User2();

        //$foo = $this->getMock();
    }

    public function testCanDoTest() {
        $this->assertInstanceOf('Application_Model_User2', $this->_model);
        //$this->assertType('Application_Model_User2',new Application_Model_User2());
    }

    public function testCanFind() {
        $this->assertTrue(true);
        $this->_model->init();
        $this->assertNotNull($this->_model->find('admin'));
    }   
}

当我运行测试时,它会给我错误:

1) Model_User2Test::testCanFind
Undefined variable: _table
application\models\User2.php:57
tests\application\models\User2Test.php:27

为什么没有定义_table?实际上它是在我创建对象时定义的?我怎么能解决它?

2 个答案:

答案 0 :(得分:2)

您将_$table声明为受保护的:

protected $_table = 'user';

因此,您无法通过课程的实例访问它。只有继承的类才能做到这一点。您需要将其声明为public,或使用getter / setter样式访问。

编辑:

static function load($id) {
    return self::_selectAndBind(
            get_class(),
                    self::getDefaultAdapter()
                    ->select()
                    // $this->_table not $table
                    ->from($_table)
                    ->where('id = ?', array($id)),
            true);
}

在您的课程中,您使用的是$ _table而不是$ this-&gt; _table。这在另一个位置是相同的。检查以确保您正确访问类变量。

答案 1 :(得分:1)

在静态方法Application_Model_User::find()中,您的查询中包含以下行:

->from($_table)

但在这种情况下,$_table是一个永远不会被设置的局部变量。听起来您想要访问$this->_table

[作为旁注:由于您已将find()定义为静态方法,因此在静态调用期间尝试引用$this时可能会遇到问题。当然,在您的测试中,您似乎确实在实例上调用find(),因此您应该在这方面做得很好。你真的需要find()作为静态方法吗?]