title: How to test controllers with CodeIgniter?
body: <p>I have a PHP web application built with CodeIgniter MVC framework. I wish to test various controller classes. I'm using <a href="http://jensroland.com/projects/toast/" rel="nofollow noreferrer">Toast</a> for unit testing. My controllers have no state, everything they process is either saved into session or passed to view to display. Creating a mock session object and testing whether that works properly is straightforward (just create a mock object and inject it with $controller->session = $mock).</p>
  
  <p>What I don't know, is how to work with views. In CodeIgniter, views are loaded as:</p>
  
  <pre><code>$this-&gt;load-&gt;view($view_name, $vars, $return);
  </code></pre>
  
  <p>Since I don't want to alter CI code, I though I could create a mock Loader and replace the original. And here lies the problem, I cannot find a way to derive a new class from CI_Loader. </p>
  
  <p>If I don't include the system/libraries/Loader.php file, the class CI_Loader is undefined and I cannot inherit from it:</p>
  
  <pre><code>class Loader_mock extends CI_Loader
  </code></pre>
  
  <p>If I do include the file (using require_once), I get the error:</p>
  
  <pre><code>Cannot redeclare class CI_Loader
  </code></pre>
  
  <p>Looks like CI code itself does not use require_once from whatever reason.</p>
  
  <p>Does anyone here have experience with unit testing CodeIgniter powered applications?</p>
  
  <p><strong>Edit:</strong> I tried to inject a real loader object at run-time into a mock class, and redirect all calls and variables with __call, __set, __get, __isset and __unset. But, it does not seem to work (I don't get any errors though, just no output, i.e. blank page from Toast). Here's the code:</p>
  
  <pre><code>class Loader_mock 
  {
      public $real_loader;
      public $varijable = array();
  
      public function Loader_mock($real)
      {
          $this-&gt;real_loader = $real;
      }
  
      public function __call($name, $arguments) 
      {
          return $this-&gt;real_loader-&gt;$name($arguments);
      }
  
      public function __set($name, $value)
      {
          return $this-&gt;real_loader-&gt;$name = $value;
      }
  
      public function __isset($name)
      {
          return isset($this-&gt;real_loader-&gt;$name);
      }
  
      public function __unset($name)
      {
          unset($this-&gt;loader-&gt;$name);
      }
  
      public function __get($name)
      {
          return $this-&gt;real_loader-&gt;$name;
      }
  
      public function view($view, $vars = array(), $return = FALSE)
      {
          $varijable = $vars;
      }
  }
  </code></pre>