0

私は一連のコンポーネント (完全なフレームワークになることを願っています) に取り組んでおり、現在、PHP セッションの抽象化を提供するコンポーネントに取り組んでいます。

コードをできる限りテストしやすいものにしようとしていますが、定義上、セッション クラスは $_SESSION スーパーグローバルの形でグローバル状態に依存します。

$ SESSION および session * 関数が 1 か所でのみ呼び出されるようにセッション クラスを実装しようとしましたが、それをテスト目的で PHPUnit でオーバーライドできます。これを行う方法。

テスト可能なセッション クラスを作成するためのより良いアプローチを提案できる場合は、ご意見をお寄せいただければ幸いです。

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

namespace gordian\reefknot\storage\session;

use gordian\reefknot\storage;

/**
 * Session management
 * 
 * Each instance of the Session object represents a "namespace" within the PHP
 * $_SESSION system.  This allows sessions to be easily managed and organized
 * within an application
 * 
 */
class Session implements storage\iface\Crud, iface\Session
{

    protected
        $name       = '',
        $storage    = NULL;


    /**
     * Add a new item to the session
     * 
     * @param mixed $data 
     * @param string $key
     * @return Session
     * @throws \InvalidArgumentException Thrown if no name is provided
     */
    public function createItem ($data, $key)
    {
        if (!empty ($key))
        {
            $key    = (string) $key;
            if (($this -> storage === NULL)
            || (!array_key_exists ($key, $this -> storage)))
            {
                $this -> storage [$key] = $data;
            }
        }
        else
        {
            throw new \Exception ('No valid key given');
        }
        return ($this);
    }

    /**
     * Delete the specified key
     * 
     * @param string $key 
     * @return Session
     */
    public function deleteItem ($key)
    {
        unset ($this -> storage [$key]);
        return ($this);
    }

    /**
     * Retrieve the data stored in the specified key
     * 
     * @param type $key 
     * @return mixed
     */
    public function readItem ($key)
    {
        return (array_key_exists ($key, $this -> storage)? 
            $this -> storage ['key']: 
            NULL);
    }

    /**
     * Update a previously stored data item to a new value
     * 
     * @param mixed $data 
     * @param string $key
     */
    public function updateItem ($data, $key)
    {
        if ($this -> storage === NULL)
        {
            throw new \RuntimeException ('Session contains no data');
        }

        if (array_key_exists ($key, $this -> storage))
        {
            $this -> storage [$key] = $data;
        }
        return ($this);
    }

    /**
     * Clear the session of all stored data
     * 
     * @return Session 
     */
    public function reset ()
    {
        $this -> storage = NULL;
        return ($this);
    }

    /**
     * Retrieve all data stored in the session
     * 
     * @return array 
     */
    public function getAll ()
    {
        return ($this -> storage);
    }

    /**
     * Return whether there is data stored in this session
     * 
     * @return bool 
     */
    public function hasData ()
    {
        return (!empty ($this -> storage));
    }

    /**
     * Initialize the back-end storage for the session
     * 
     * This method provides access for this class to the underlying PHP session
     * mechanism.  
     * 
     * @return bool Whether the newly initialized session contains data or not
     * @throws \RuntimeException Will be thrown if the session failed to start
     */
    protected function initStorage ()
    {
        // Check that storage hasn't already been initialized
        if ($this -> storage === NULL)
        {
            // Attempt to start the session if it hasn't already been started
            if ((session_id () === '')
            && ((headers_sent ()) 
            || ((!session_start ()))))
            {
                throw new \RuntimeException ('Unable to start session at this time');
            }
            // Alias our instance storage to the named $_SESSION variable
            $this -> storage    =& $_SESSION [$this -> name];
        }
        return ($this -> hasData ());
    }

    /**
     * Class constructor
     * 
     * @param string $sessName
     * @throws \InvalidArgumentException Thrown if no session name is provided
     */
    public function __construct ($sessName)
    {
        if (!empty ($sessName))
        {
            $this -> name   = $sessName;
            $this -> initStorage ();
        }
        else
        {
            throw new \InvalidArgumentException ('Session must have a name');
        }
    }
}

テストのため、現在の計画では initStorage() を代わりに内部配列をセットアップするだけのメソッドに置き換えることです。あなたがより良いアプローチを提案できるなら、私はそれを聞きたいと思っています。

4

2 に答える 2

1

私が正しく理解していれば..

ネイティブ セッション管理の抽象化を作成して、セッション ストレージ ヘルパーが実際に session_* 呼び出しを実行したり、$_SESSION に直接アクセスしたりする必要がないようにします。

1 つは実際に正しいことを行い、もう 1 つは偽の session_*() と $_SESSION を除き、コンストラクターで SESSIONCLASS::start() と SESSIONCLASS::getVar(name) を呼び出すだけです。その後、「セッション」を完全にテストできます。

于 2012-02-26T08:51:22.840 に答える
1

は通常の配列であるため$_SESSION、参照を介してアクセスする理由はありません。さまざまな読み取り/書き込みメソッドは、直接操作する必要があります。setUp()テスト ケースのメソッドで配列をクリアできます。参照を使用すると、見返りがなく、クラスが過度に複雑になります。

session_id()単体テストを行うときは、や などの組み込みの PHP 関数をテストする必要はありませんheaders_sent()。クラスの部分モックまたはこの 1 つのメソッドをオーバーライドするテスト専用サブクラスを作成します。

于 2012-02-26T09:04:48.553 に答える