2009-07-16 30 views
12

私はCodeIgniter MVCフレームワークで構築されたPHP Webアプリケーションを持っています。さまざまなコントローラークラスをテストしたい。ユニットテストにToastを使用しています。私のコントローラには状態はなく、処理するものはすべてセッションに保存されるか、表示するために渡されます。擬似セッションオブジェクトを作成し、それが正しく動作するかどうかをテストするのは簡単です(擬似オブジェクトを作成し、$ controller-> session = $ mockで注入するだけです)。CodeIgniterでコントローラをテストするには?

私が知りませんが、どのようにビューを操作するかです。私はしかし、私はモックローダを作成し、元のを置き換えることができ、CIのコードを変更する必要はありませんので

$this->load->view($view_name, $vars, $return); 

:CodeIgniterのでは、ビューは次のようにロードされます。そしてここに問題があります。私はCI_Loaderから新しいクラスを派生させる方法を見つけることができません。

私はシステム/ライブラリ/ Loader.phpファイルが含まれていない場合は、クラスCI_Loaderが定義されていないと私はそれを継承することはできません。

class Loader_mock extends CI_Loader 

私は(のrequire_onceを使用して)ファイルを含める場合、私はエラーを取得する:

Cannot redeclare class CI_Loader 

は、それ自体が何らかの理由からのrequire_onceを使用していないCIコードのように見えます。

ここで誰もCodeIgniterで動くアプリケーションをテストした経験がありますか?

編集:私はモッククラスに実行時に実際のローダオブジェクトを注入し、__call、__set、__get、__issetと__unset持つすべての呼び出しと変数をリダイレクトしようとしました。しかし、それは動作していないようです(私はエラーは発生しません。出力はありません。Toastの空白ページ)。コードは次のとおりです。

class Loader_mock 
{ 
    public $real_loader; 
    public $varijable = array(); 

    public function Loader_mock($real) 
    { 
     $this->real_loader = $real; 
    } 

    public function __call($name, $arguments) 
    { 
     return $this->real_loader->$name($arguments); 
    } 

    public function __set($name, $value) 
    { 
     return $this->real_loader->$name = $value; 
    } 

    public function __isset($name) 
    { 
     return isset($this->real_loader->$name); 
    } 

    public function __unset($name) 
    { 
     unset($this->loader->$name); 
    } 

    public function __get($name) 
    { 
     return $this->real_loader->$name; 
    } 

    public function view($view, $vars = array(), $return = FALSE) 
    { 
     $varijable = $vars; 
    } 
} 

答えて

4

またグルートをReinの、あなたはこれを行うことができます:

$CI =& get_instance(); 
$CI = load_class('Loader'); 

class MockLoader extends CI_Loader 
{ 
    function __construct() 
    { 
     parent::__construct(); 
    } 
} 

をその後の$ this - >負荷=新しいMockLoaderを行う()あなたのコントローラで。

+0

いいアイデア、ありがとう。 –

2

私の現在の解決策は、requireの代わりにrequire_onceを使用するようにCodeIgniterコードを変更することです。ここで私は、誰かが、彼らはそれを受け入れるまで、同じことを行う必要がある場合にはCIの開発者に送信するつもりだパッチです:

diff --git a/system/codeigniter/Common.php b/system/codeigniter/Common.php 
--- a/system/codeigniter/Common.php 
+++ b/system/codeigniter/Common.php 
@@ -100,20 +100,20 @@ function &load_class($class, $instantiate = TRUE) 
     // folder we'll load the native class from the system/libraries folder. 
     if (file_exists(APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT)) 
     { 
-    require(BASEPATH.'libraries/'.$class.EXT); 
-    require(APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT); 
+    require_once(BASEPATH.'libraries/'.$class.EXT); 
+    require_once(APPPATH.'libraries/'.config_item('subclass_prefix').$class.EXT); 
       $is_subclass = TRUE; 
     } 
     else 
     { 
       if (file_exists(APPPATH.'libraries/'.$class.EXT)) 
       { 
-      require(APPPATH.'libraries/'.$class.EXT); 
+      require_once(APPPATH.'libraries/'.$class.EXT); 
         $is_subclass = FALSE; 
       } 
       else 
       { 
-      require(BASEPATH.'libraries/'.$class.EXT); 
+      require_once(BASEPATH.'libraries/'.$class.EXT); 
         $is_subclass = FALSE; 
       } 
     } 
1

私はテストで多くのお手伝いをすることはできませんが、私はあなたが拡張することができますCIライブラリ。

MY_Loaderクラスは/application/libraries/MY_Loader.phpの中に独自に作成できます。

<?php 
    class MY_Loader extends CI_Loader { 

    function view($view, $vars = array(), $return = FALSE) { 
     echo 'My custom code goes here'; 
    } 

    } 

CodeIgniterに自動的に表示されます。元のライブラリで置き換えたい機能を入れるだけです。他のすべてはオリジナルを使用します。

詳細については、CI manual page for creating core system classesをご覧ください。

+3

+1。しかし、単体テストの黄金のルールは、単体テストのフックを有効にするためだけにシステムを変更する必要はないということです。理想的には、ユニットテストスイートに含まれていないクラスにはユニットテスト手荷物を持たないでください。また、1つのクラスのテスト用のすべてのユニットテストコードを同じファイルに保存すると、管理が簡単になります(実稼働環境にデプロイする際にユニットテストコードも削除されます)。先端のために –

1

私はあなたが使用しようとしているコードに感心しています。

今、私はCodeIgniterの「フック」クラスがあなたの問題にどのように役立つのだろうかと思います。

http://codeigniter.com/user_guide/general/hooks.html

敬具、 は

+0

+1。それは実行可能かもしれないが、多少厄介な方法であるようだ。私はCodeIgniterにパッチを当てることにしました。これは簡単な変更です。いつか主流のCIコードに入ることを願っています(なぜそうはならないのかわかりません)ので、パッチを当てる必要はありません。新しいバージョンがリリースされました。 –

0

コントローラにはドメインロジックが含まれていてはいけません。ユニットテストはここでは意味がありません。

代わりに、受け入れテストでコントローラとビューをテストします。

+0

まあ、コントローラにはドメインロジックがないのに、ユーザー入力を管理するのは*責任です。その入力に基づいてモデルレイヤーの状態を変更します。これはコントローラの単体テストに重点を置くところです。 –

+0

私はコントローラがモデルレイヤー内の何かの状態を変更する必要はないと思います。それは単に要求を受け取り、それをモデルレイヤーに渡すべきです(Webセキュリティなどの処理後)。 エンティティまたはデータを変更する場合は、テストする必要があると思います。しかし、まずそれをやってはいけません。 – Patrick

+1

ユーザ名とパスワードをモデルレイヤに渡すと、そのレイヤの状態が変更されます。または、保存する記事のタイトルを送信すると、モデルレイヤーの状態も変更されます。そして、あなたが「Webセキュリティ」と呼んでいたことは、モデルレイヤーで実行されるべきものです(おそらく、CSRF防止以外に、 'Request'インスタンスを初期化すると良いでしょう)。しかし、全く異なる[概念](http://stackoverflow.com/a/5864000/727208)に同じ用語を使用している可能性もあります。 –

関連する問題