Merge pull request #1226 from toopay/unit-tests

Improve Unit tests
diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php
index 39c24b2..9f89d1b 100644
--- a/tests/Bootstrap.php
+++ b/tests/Bootstrap.php
@@ -6,16 +6,16 @@
 
 $dir = realpath(dirname(__FILE__));
 
-
 // Path constants
 define('PROJECT_BASE',	realpath($dir.'/../').'/');
 define('BASEPATH',		PROJECT_BASE.'system/');
 define('APPPATH',		PROJECT_BASE.'application/');
 define('VIEWPATH',		PROJECT_BASE.'');
 
-
 // Prep our test environment
-require_once $dir.'/lib/common.php';
-require_once $dir.'/lib/ci_testcase.php';
+require_once 'vfsStream/vfsStream.php';
+include_once $dir.'/mocks/core/common.php';
+include_once $dir.'/mocks/autoloader.php';
+spl_autoload_register('autoload');
 
 unset($dir);
\ No newline at end of file
diff --git a/tests/codeigniter/core/Common_test.php b/tests/codeigniter/core/Common_test.php
index cec1298..dded2e8 100644
--- a/tests/codeigniter/core/Common_test.php
+++ b/tests/codeigniter/core/Common_test.php
@@ -1,9 +1,6 @@
 <?php
 
-require_once(BASEPATH.'helpers/email_helper.php');
-
-class Common_test extends CI_TestCase
-{
+class Common_test extends CI_TestCase {
 	
 	// ------------------------------------------------------------------------
 	
diff --git a/tests/codeigniter/core/Loader_test.php b/tests/codeigniter/core/Loader_test.php
index b86fd34..4300865 100644
--- a/tests/codeigniter/core/Loader_test.php
+++ b/tests/codeigniter/core/Loader_test.php
@@ -1,38 +1,5 @@
 <?php
 
-require_once 'vfsStream/vfsStream.php';
-require_once BASEPATH.'/core/Loader.php';
-
-class Extended_Loader extends CI_Loader {
-	
-	/**
-	 * Since we use paths to load up models, views, etc, we need the ability to
-	 * mock up the file system so when core tests are run, we aren't mucking
-	 * in the application directory.  this will give finer grained control over
-	 * these tests.  So yeah, while this looks odd, I need to overwrite protected
-	 * class vars in the loader.  So here we go...
-	 *
-	 * @covers CI_Loader::__construct()
-	 */
-	public function __construct()
-	{
-		vfsStreamWrapper::register();
-		vfsStreamWrapper::setRoot(new vfsStreamDirectory('application'));
-		
-		$this->models_dir 	= vfsStream::newDirectory('models')->at(vfsStreamWrapper::getRoot());
-		$this->libs_dir 	= vfsStream::newDirectory('libraries')->at(vfsStreamWrapper::getRoot());
-		$this->helpers_dir 	= vfsStream::newDirectory('helpers')->at(vfsStreamWrapper::getRoot());
-		$this->views_dir 	= vfsStream::newDirectory('views')->at(vfsStreamWrapper::getRoot());
-		
-		$this->_ci_ob_level  		= ob_get_level();
-		$this->_ci_library_paths	= array(vfsStream::url('application').'/', BASEPATH);
-		$this->_ci_helper_paths 	= array(vfsStream::url('application').'/', BASEPATH);
-		$this->_ci_model_paths 		= array(vfsStream::url('application').'/');
-		$this->_ci_view_paths 		= array(vfsStream::url('application').'/views/' => TRUE);
-	}
-}
-
-
 class Loader_test extends CI_TestCase {
 	
 	private $ci_obj;
@@ -40,7 +7,7 @@
 	public function set_up()
 	{
 		// Instantiate a new loader
-		$this->load = new Extended_Loader();
+		$this->load = new Mock_Core_Loader();
 		
 		// mock up a ci instance
 		$this->ci_obj = new StdClass;
@@ -265,7 +232,4 @@
 
 	// --------------------------------------------------------------------
 	
-	
-	
-	
 }
diff --git a/tests/codeigniter/core/URI_test.php b/tests/codeigniter/core/URI_test.php
index 40252aa..e340ddf 100644
--- a/tests/codeigniter/core/URI_test.php
+++ b/tests/codeigniter/core/URI_test.php
@@ -1,41 +1,10 @@
 <?php
 
-require BASEPATH.'core/URI.php';
-
-/**
- * Extend the URI class
- *  - override contructor
- *  - override CLI detection
- */
-class URI_extended extends CI_URI {
-	
-	public function __construct()
-	{
-		$test = CI_TestCase::instance();
-		$cls =& $test->ci_core_class('cfg');
-		
-		// set predictable config values
-		$test->ci_set_config(array(
-			'index_page'		=> 'index.php',
-			'base_url'			=> 'http://example.com/',
-			'subclass_prefix'	=> 'MY_'
-		));
-
-		$this->config = new $cls;	
-
-	}
-	
-	protected function _is_cli_request()
-	{
-		return FALSE;
-	}
-}
-
 class URI_test extends CI_TestCase {
 	
 	public function set_up()
 	{
-		$this->uri = new URI_extended();
+		$this->uri = new Mock_Core_URI();
 	}
 
 	// --------------------------------------------------------------------
diff --git a/tests/codeigniter/database/.gitkeep b/tests/codeigniter/database/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/codeigniter/database/.gitkeep
diff --git a/tests/codeigniter/helpers/array_helper_test.php b/tests/codeigniter/helpers/array_helper_test.php
index 62559de..9cd1596 100644
--- a/tests/codeigniter/helpers/array_helper_test.php
+++ b/tests/codeigniter/helpers/array_helper_test.php
@@ -1,13 +1,11 @@
 <?php
 
-// OLD TEST FORMAT: DO NOT COPY
-
-require_once(BASEPATH.'helpers/array_helper.php');
-
-class Array_helper_test extends CI_TestCase
-{
+class Array_helper_test extends CI_TestCase {
+	
 	public function set_up()
 	{
+		$this->helper('array');
+
 		$this->my_array = array(
 			'foo'		=> 'bar',
 			'sally'		=> 'jim',
diff --git a/tests/codeigniter/helpers/date_helper_test.php b/tests/codeigniter/helpers/date_helper_test.php
index 662d164..17d1ef2 100644
--- a/tests/codeigniter/helpers/date_helper_test.php
+++ b/tests/codeigniter/helpers/date_helper_test.php
@@ -1,8 +1,12 @@
 <?php
-require_once BASEPATH.'helpers/date_helper.php';
 
-class Date_helper_test extends CI_TestCase
-{
+class Date_helper_test extends CI_TestCase {
+
+	public function set_up()
+	{
+		$this->helper('date');
+	}
+
 	// ------------------------------------------------------------------------
 
 	public function test_now_local()
diff --git a/tests/codeigniter/helpers/directory_helper_test.php b/tests/codeigniter/helpers/directory_helper_test.php
index 3fae81b..3937d29 100644
--- a/tests/codeigniter/helpers/directory_helper_test.php
+++ b/tests/codeigniter/helpers/directory_helper_test.php
@@ -1,12 +1,11 @@
 <?php
 
-require_once 'vfsStream/vfsStream.php';
-require BASEPATH.'helpers/directory_helper.php';
-
-class Directory_helper_test extends CI_TestCase
-{
+class Directory_helper_test extends CI_TestCase {
+	
 	public function set_up()
 	{
+		$this->helper('directory');
+
 		vfsStreamWrapper::register();
 		vfsStreamWrapper::setRoot(new vfsStreamDirectory('testDir'));
 		
diff --git a/tests/codeigniter/helpers/email_helper_test.php b/tests/codeigniter/helpers/email_helper_test.php
index 7324e81..a01f3d5 100644
--- a/tests/codeigniter/helpers/email_helper_test.php
+++ b/tests/codeigniter/helpers/email_helper_test.php
@@ -1,10 +1,12 @@
 <?php
 
-require_once(BASEPATH.'helpers/email_helper.php');
+class Email_helper_test extends CI_TestCase {
 
-class Email_helper_test extends CI_TestCase
-{
-	
+	public function set_up()
+	{
+		$this->helper('email');
+	}
+
 	public function test_valid_email()
 	{
 		$this->assertEquals(FALSE, valid_email('test'));
diff --git a/tests/codeigniter/helpers/file_helper_test.php b/tests/codeigniter/helpers/file_helper_test.php
index a596a03..4b9c294 100644
--- a/tests/codeigniter/helpers/file_helper_test.php
+++ b/tests/codeigniter/helpers/file_helper_test.php
@@ -1,12 +1,11 @@
 <?php
 
-require_once 'vfsStream/vfsStream.php';
-require BASEPATH.'helpers/file_helper.php';
+class File_helper_Test extends CI_TestCase {
 
-class File_helper_Test extends CI_TestCase
-{
 	public function set_up()
 	{
+		$this->helper('file');
+		
 		vfsStreamWrapper::register();
 		vfsStreamWrapper::setRoot(new vfsStreamDirectory('testDir'));
 		
diff --git a/tests/codeigniter/helpers/html_helper_test.php b/tests/codeigniter/helpers/html_helper_test.php
index 553fc2b..28974b0 100644
--- a/tests/codeigniter/helpers/html_helper_test.php
+++ b/tests/codeigniter/helpers/html_helper_test.php
@@ -1,9 +1,11 @@
 <?php
 
-require_once(BASEPATH.'helpers/html_helper.php');
+class Html_helper_test extends CI_TestCase {
 
-class Html_helper_test extends CI_TestCase
-{
+	public function set_up()
+	{
+		$this->helper('html');
+	}
 	
 	// ------------------------------------------------------------------------
 	
diff --git a/tests/codeigniter/helpers/inflector_helper_test.php b/tests/codeigniter/helpers/inflector_helper_test.php
index 472e28a..9e94787 100644
--- a/tests/codeigniter/helpers/inflector_helper_test.php
+++ b/tests/codeigniter/helpers/inflector_helper_test.php
@@ -1,9 +1,11 @@
 <?php
 
-require_once(BASEPATH.'helpers/inflector_helper.php');
-
 class Inflector_helper_test extends CI_TestCase {
 	
+	public function set_up()
+	{
+		$this->helper('inflector');
+	}
 	
 	public function test_singular()
 	{
diff --git a/tests/codeigniter/helpers/number_helper_test.php b/tests/codeigniter/helpers/number_helper_test.php
index 3322b24..4bb9a91 100644
--- a/tests/codeigniter/helpers/number_helper_test.php
+++ b/tests/codeigniter/helpers/number_helper_test.php
@@ -1,12 +1,11 @@
 <?php
 
-require_once BASEPATH.'helpers/number_helper.php';
-
-class Number_helper_test extends CI_TestCase
-{
+class Number_helper_test extends CI_TestCase {
 	
 	public function set_up()
 	{
+		$this->helper('number');
+		
 		// Grab the core lang class
 		$lang_cls = $this->ci_core_class('lang');
 		
diff --git a/tests/codeigniter/helpers/path_helper_test.php b/tests/codeigniter/helpers/path_helper_test.php
index 2e6cc63..632f575 100644
--- a/tests/codeigniter/helpers/path_helper_test.php
+++ b/tests/codeigniter/helpers/path_helper_test.php
@@ -1,9 +1,12 @@
 <?php
 
-require BASEPATH . 'helpers/path_helper.php';
+class Path_helper_test extends CI_TestCase {
 
-class Path_helper_test extends CI_TestCase 
-{
+	public function set_up()
+	{
+		$this->helper('path');
+	}
+
 	public function test_set_realpath()
 	{				
 		$expected = getcwd() . DIRECTORY_SEPARATOR;
diff --git a/tests/codeigniter/helpers/string_helper_test.php b/tests/codeigniter/helpers/string_helper_test.php
index a884d62..29c3d65 100644
--- a/tests/codeigniter/helpers/string_helper_test.php
+++ b/tests/codeigniter/helpers/string_helper_test.php
@@ -1,9 +1,12 @@
 <?php
 
-require_once(BASEPATH.'helpers/string_helper.php');
+class String_helper_test extends CI_TestCase {
 
-class String_helper_test extends CI_TestCase
-{
+	public function set_up()
+	{
+		$this->helper('string');
+	}
+
 	public function test_strip_slashes()
 	{
 		$expected = array(
diff --git a/tests/codeigniter/helpers/text_helper_test.php b/tests/codeigniter/helpers/text_helper_test.php
index a0866e6..584066b 100644
--- a/tests/codeigniter/helpers/text_helper_test.php
+++ b/tests/codeigniter/helpers/text_helper_test.php
@@ -1,13 +1,13 @@
 <?php
 
-require_once(BASEPATH.'helpers/text_helper.php');
+class Text_helper_test extends CI_TestCase {
 
-class Text_helper_test extends CI_TestCase
-{
 	private $_long_string;
 	
 	public function set_up()
 	{
+		$this->helper('text');
+		
 		$this->_long_string = 'Once upon a time, a framework had no tests.  It sad.  So some nice people began to write tests.  The more time that went on, the happier it became.  Everyone was happy.';
 	}
 	
diff --git a/tests/codeigniter/helpers/url_helper_test.php b/tests/codeigniter/helpers/url_helper_test.php
index 51a8cc7..c561809 100644
--- a/tests/codeigniter/helpers/url_helper_test.php
+++ b/tests/codeigniter/helpers/url_helper_test.php
@@ -1,9 +1,12 @@
 <?php
 
-require_once(BASEPATH.'helpers/url_helper.php');
+class Url_helper_test extends CI_TestCase {
 
-class Url_helper_test extends CI_TestCase
-{
+	public function set_up()
+	{
+		$this->helper('url');
+	}
+
 	public function test_url_title()
 	{
 		$words = array(
diff --git a/tests/codeigniter/helpers/xml_helper_test.php b/tests/codeigniter/helpers/xml_helper_test.php
index 49f49e1..a83fef9 100644
--- a/tests/codeigniter/helpers/xml_helper_test.php
+++ b/tests/codeigniter/helpers/xml_helper_test.php
@@ -1,9 +1,11 @@
 <?php
 
-require_once(BASEPATH.'helpers/xml_helper.php');
+class Xml_helper_test extends CI_TestCase {
 
-class Xml_helper_test extends CI_TestCase
-{
+	public function set_up()
+	{
+		$this->helper('xml');
+	}
 	
 	public function test_xml_convert()
 	{
diff --git a/tests/codeigniter/libraries/Parser_test.php b/tests/codeigniter/libraries/Parser_test.php
index b4580a4..c3d88fa 100644
--- a/tests/codeigniter/libraries/Parser_test.php
+++ b/tests/codeigniter/libraries/Parser_test.php
@@ -1,14 +1,11 @@
 <?php
 
-require BASEPATH.'libraries/Parser.php';
-
-class Parser_test extends CI_TestCase
-{
+class Parser_test extends CI_TestCase {
 	
 	public function set_up()
 	{
 		$obj = new StdClass;
-		$obj->parser = new CI_Parser();
+		$obj->parser = new Mock_Libraries_Parser();
 		
 		$this->ci_instance($obj);
 		
diff --git a/tests/codeigniter/libraries/Table_test.php b/tests/codeigniter/libraries/Table_test.php
index 0208a46..13f338c 100644
--- a/tests/codeigniter/libraries/Table_test.php
+++ b/tests/codeigniter/libraries/Table_test.php
@@ -1,14 +1,11 @@
 <?php
 
-require BASEPATH.'libraries/Table.php';
-
-class Table_test extends CI_TestCase
-{
+class Table_test extends CI_TestCase {
 
 	public function set_up()
 	{
 		$obj = new StdClass;
-		$obj->table = new CI_table();
+		$obj->table = new Mock_Libraries_Table();
 		
 		$this->ci_instance($obj);
 		
@@ -103,53 +100,23 @@
 			array('data' => 'size')
 		);
 		
-		// test what would be discreet args,
-		// basically means a single array as the calling method
-		// will use func_get_args()
-		
-		$reflectionOfTable = new ReflectionClass($this->table);
-		$method = $reflectionOfTable->getMethod('_prep_args');
-		
-		$method->setAccessible(true);
-			
 		$this->assertEquals(
 			$expected,
-			$method->invokeArgs(
-				$this->table, array(array('name', 'color', 'size'), 'discreet')
-			)
+			$this->table->prep_args(array('name', 'color', 'size'))
 		);
-		
-		// test what would be a single array argument. Again, nested
-		// due to func_get_args on calling methods
-		$this->assertEquals(
-			$expected,
-			$method->invokeArgs(
-				$this->table, array(array('name', 'color', 'size'), 'array')
-			)
-		);
-		
-		
+
 		// with cell attributes
-		
 		// need to add that new argument row to our expected outcome
 		$expected[] = array('data' => 'weight', 'class' => 'awesome');
 
 		$this->assertEquals(
 			$expected,
-			$method->invokeArgs(
-				$this->table, array(array('name', 'color', 'size', array('data' => 'weight', 'class' => 'awesome')), 'attributes')
-			)
+			$this->table->prep_args(array('name', 'color', 'size', array('data' => 'weight', 'class' => 'awesome')))
 		);
 	}
 	
 	public function test_default_template_keys()
 	{
-		$reflectionOfTable = new ReflectionClass($this->table);
-		$method = $reflectionOfTable->getMethod('_default_template');
-		
-		$method->setAccessible(true);
-		
-		$deft_template = $method->invoke($this->table);
 		$keys = array(
 			'table_open',
 			'thead_open', 'thead_close',
@@ -162,29 +129,24 @@
 		
 		foreach ($keys as $key)
 		{
-			$this->assertArrayHasKey($key, $deft_template);
+			$this->assertArrayHasKey($key, $this->table->default_template());
 		}
 	}
 	
 	public function test_compile_template()
 	{
-		$reflectionOfTable = new ReflectionClass($this->table);
-		$method = $reflectionOfTable->getMethod('_compile_template');
-		
-		$method->setAccessible(true);
-		
 		$this->assertFalse($this->table->set_template('invalid_junk'));
 		
 		// non default key
 		$this->table->set_template(array('nonsense' => 'foo'));
-		$method->invoke($this->table);
+		$this->table->compile_template();
 		
 		$this->assertArrayHasKey('nonsense', $this->table->template);
 		$this->assertEquals('foo', $this->table->template['nonsense']);
 		
 		// override default
 		$this->table->set_template(array('table_close' => '</table junk>'));
-		$method->invoke($this->table);
+		$this->table->compile_template();
 		
 		$this->assertArrayHasKey('table_close', $this->table->template);
 		$this->assertEquals('</table junk>', $this->table->template['table_close']);
@@ -250,13 +212,8 @@
 	
 	public function test_set_from_array()
 	{
-		$reflectionOfTable = new ReflectionClass($this->table);
-		$method = $reflectionOfTable->getMethod('_set_from_array');
-		
-		$method->setAccessible(true);
-				
-		$this->assertFalse($method->invokeArgs($this->table, array('bogus')));
-		$this->assertFalse($method->invoke($this->table, array()));
+		$this->assertFalse($this->table->set_from_array('bogus'));
+		$this->assertFalse($this->table->set_from_array(NULL));
 		
 		$data = array(
 			array('name', 'color', 'number'),
@@ -264,7 +221,7 @@
 			array('Katie', 'Blue')				
 		);
 		
-		$method->invokeArgs($this->table, array($data, FALSE));
+		$this->table->set_from_array($data, FALSE);
 		$this->assertEmpty($this->table->heading);
 		
 		$this->table->clear();
@@ -280,7 +237,7 @@
 			array('data' => 'Blue'),
 		);
 		
-		$method->invokeArgs($this->table, array($data));
+		$this->table->set_from_array($data);
 		$this->assertEquals(count($this->table->rows), 2);
 		
 		$this->assertEquals(
@@ -296,11 +253,6 @@
 	
 	function test_set_from_object()
 	{
-		$reflectionOfTable = new ReflectionClass($this->table);
-		$method = $reflectionOfTable->getMethod('_set_from_object');
-		
-		$method->setAccessible(true);
-
 		// Make a stub of query instance
 		$query = new CI_TestCase();
 		$query->list_fields = function(){
@@ -326,7 +278,7 @@
 			'email' => array('data' => 'foo@bar.com'),
 		);
 
-		$method->invokeArgs($this->table, array($query));
+		$this->table->set_from_object($query);
 
 		$this->assertEquals(
 			$expected_heading,
diff --git a/tests/codeigniter/libraries/Typography_test.php b/tests/codeigniter/libraries/Typography_test.php
index a0533ba..250aefb 100644
--- a/tests/codeigniter/libraries/Typography_test.php
+++ b/tests/codeigniter/libraries/Typography_test.php
@@ -1,14 +1,11 @@
 <?php
 
-require BASEPATH.'libraries/Typography.php';
-
-class Typography_test extends CI_TestCase
-{
+class Typography_test extends CI_TestCase {
 
 	public function set_up()
 	{
 		$obj = new StdClass;
-		$obj->type = new CI_Typography();
+		$obj->type = new Mock_Libraries_Typography();
 		
 		$this->ci_instance($obj);
 		
diff --git a/tests/codeigniter/libraries/User_agent_test.php b/tests/codeigniter/libraries/Useragent_test.php
similarity index 93%
rename from tests/codeigniter/libraries/User_agent_test.php
rename to tests/codeigniter/libraries/Useragent_test.php
index 6f9e871..7dad7ac 100644
--- a/tests/codeigniter/libraries/User_agent_test.php
+++ b/tests/codeigniter/libraries/Useragent_test.php
@@ -1,11 +1,7 @@
 <?php
 
-require BASEPATH.'libraries/User_agent.php';
-
-// This class needs some work...
-
-class UserAgent_test extends CI_TestCase
-{
+class UserAgent_test extends CI_TestCase {
+	
 	protected $_user_agent = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27';
 	protected $_mobile_ua = 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7';
 
@@ -15,7 +11,7 @@
 		$_SERVER['HTTP_USER_AGENT'] = $this->_user_agent;
 
 		$obj = new StdClass;
-		$obj->agent = new CI_User_agent();
+		$obj->agent = new Mock_Libraries_UserAgent();
 
 		$this->ci_instance($obj);
 
diff --git a/tests/mocks/autoloader.php b/tests/mocks/autoloader.php
new file mode 100644
index 0000000..dd59292
--- /dev/null
+++ b/tests/mocks/autoloader.php
@@ -0,0 +1,79 @@
+<?php
+
+// This autoloader provide convinient way to working with mock object
+// make the test looks natural. This autoloader support cascade file loading as well
+// within mocks directory.
+//
+// Prototype :
+//
+// include_once('Mock_Core_Loader') 					// Will load ./mocks/core/loader.php
+// $mock_table = new Mock_Libraries_Table(); 			// Will load ./mocks/libraries/table.php
+// $mock_database_driver = new Mock_Database_Driver();	// Will load ./mocks/database/driver.php 
+// and so on...
+function autoload($class) 
+{
+	$dir = realpath(dirname(__FILE__)).DIRECTORY_SEPARATOR;
+
+	$ci_core = array(
+		'Benchmark', 'Config', 'Controller',
+		'Exceptions', 'Hooks', 'Input',
+		'Lang', 'Loader', 'Model',
+		'Output', 'Router', 'Security',
+		'URI', 'Utf8',
+	);
+
+	$ci_libraries = array(
+		'Calendar', 'Cart', 'Driver',
+		'Email', 'Encrypt', 'Form_validation',
+		'Ftp', 'Image_lib', 'Javascript',
+		'Log', 'Migration', 'Pagination',
+		'Parser', 'Profiler', 'Session',
+		'Table', 'Trackback', 'Typography',
+		'Unit_test', 'Upload', 'User_agent',
+		'Xmlrpc', 'Zip',
+	);
+
+	if (strpos($class, 'Mock_') === 0)
+	{
+		$class = str_replace(array('Mock_', '_'), array('', DIRECTORY_SEPARATOR), $class);
+		$class = strtolower($class);
+	}
+	elseif (strpos($class, 'CI_') === 0)
+	{
+		$fragments = explode('_', $class, 2);
+		$subclass = next($fragments);
+
+		if (in_array($subclass, $ci_core))
+		{
+			$dir = BASEPATH.'core'.DIRECTORY_SEPARATOR;
+			$class = $subclass;
+		}
+		elseif (in_array($subclass, $ci_libraries))
+		{
+			$dir = BASEPATH.'libraries'.DIRECTORY_SEPARATOR;
+			$class = $subclass;
+		}
+		else
+		{
+			$class = strtolower($class);
+		}
+	}
+
+	$file = $dir.$class.'.php';
+
+	if ( ! file_exists($file))
+	{
+		$trace = debug_backtrace();
+
+		// If the autoload call came from `class_exists` or `file_exists`, 
+		// we skipped and return FALSE
+		if ($trace[2]['function'] == 'class_exists' OR $trace[2]['function'] == 'file_exists')
+		{
+			return FALSE;
+		}
+
+	    throw new InvalidArgumentException("Unable to load $class.");
+	}
+
+	include_once($file);
+}
\ No newline at end of file
diff --git a/tests/lib/ci_testcase.php b/tests/mocks/ci_testcase.php
similarity index 95%
rename from tests/lib/ci_testcase.php
rename to tests/mocks/ci_testcase.php
index afccee0..f327e6b 100644
--- a/tests/lib/ci_testcase.php
+++ b/tests/mocks/ci_testcase.php
@@ -1,9 +1,5 @@
 <?php
 
-
-// Need a way to change dependencies (core libs and laoded libs)
-// Need a way to set the CI class
-
 class CI_TestCase extends PHPUnit_Framework_TestCase {
 	
 	protected $ci_config;
@@ -20,7 +16,6 @@
 		'security'	=> 'sec',
 		'input'		=> 'in',
 		'lang'		=> 'lang',
-		// @todo the loader is an edge case
 		'loader'	=> 'load',
 		'model'		=> 'model'
 	);
@@ -53,6 +48,13 @@
 			$this->tear_down();
 		}
 	}
+
+	// --------------------------------------------------------------------
+	
+	public static function instance()
+	{
+		return self::$ci_test_instance;
+	}
 	
 	// --------------------------------------------------------------------
 	
@@ -67,6 +69,13 @@
 			$this->ci_config[$key] = $val;
 		}
 	}
+
+	// --------------------------------------------------------------------
+	
+	function ci_get_config()
+	{
+		return $this->ci_config;
+	}
 	
 	// --------------------------------------------------------------------
 	
@@ -158,19 +167,12 @@
 		self::$ci_test_instance = $this;
 		parent::runBare();
 	}
-	
+
 	// --------------------------------------------------------------------
 	
-	public static function instance()
+	function helper($name)
 	{
-		return self::$ci_test_instance;
-	}
-	
-	// --------------------------------------------------------------------
-	
-	function ci_get_config()
-	{
-		return $this->ci_config;
+		require_once(BASEPATH.'helpers/'.$name.'_helper.php');
 	}
 
 	// --------------------------------------------------------------------
diff --git a/tests/lib/common.php b/tests/mocks/core/common.php
similarity index 99%
rename from tests/lib/common.php
rename to tests/mocks/core/common.php
index 4a83258..fc94d7f 100644
--- a/tests/lib/common.php
+++ b/tests/mocks/core/common.php
@@ -129,4 +129,4 @@
 	return TRUE;
 }
 
-// EOF
+// EOF
\ No newline at end of file
diff --git a/tests/mocks/core/loader.php b/tests/mocks/core/loader.php
new file mode 100644
index 0000000..d4b29bb
--- /dev/null
+++ b/tests/mocks/core/loader.php
@@ -0,0 +1,30 @@
+<?php
+
+class Mock_Core_Loader extends CI_Loader {
+	
+	/**
+	 * Since we use paths to load up models, views, etc, we need the ability to
+	 * mock up the file system so when core tests are run, we aren't mucking
+	 * in the application directory.  this will give finer grained control over
+	 * these tests.  So yeah, while this looks odd, I need to overwrite protected
+	 * class vars in the loader.  So here we go...
+	 *
+	 * @covers CI_Loader::__construct()
+	 */
+	public function __construct()
+	{
+		vfsStreamWrapper::register();
+		vfsStreamWrapper::setRoot(new vfsStreamDirectory('application'));
+		
+		$this->models_dir 	= vfsStream::newDirectory('models')->at(vfsStreamWrapper::getRoot());
+		$this->libs_dir 	= vfsStream::newDirectory('libraries')->at(vfsStreamWrapper::getRoot());
+		$this->helpers_dir 	= vfsStream::newDirectory('helpers')->at(vfsStreamWrapper::getRoot());
+		$this->views_dir 	= vfsStream::newDirectory('views')->at(vfsStreamWrapper::getRoot());
+		
+		$this->_ci_ob_level  		= ob_get_level();
+		$this->_ci_library_paths	= array(vfsStream::url('application').'/', BASEPATH);
+		$this->_ci_helper_paths 	= array(vfsStream::url('application').'/', BASEPATH);
+		$this->_ci_model_paths 		= array(vfsStream::url('application').'/');
+		$this->_ci_view_paths 		= array(vfsStream::url('application').'/views/' => TRUE);
+	}
+}
\ No newline at end of file
diff --git a/tests/mocks/core/uri.php b/tests/mocks/core/uri.php
new file mode 100644
index 0000000..b694609
--- /dev/null
+++ b/tests/mocks/core/uri.php
@@ -0,0 +1,25 @@
+<?php
+
+class Mock_Core_URI extends CI_URI {
+	
+	public function __construct()
+	{
+		$test = CI_TestCase::instance();
+		$cls =& $test->ci_core_class('cfg');
+		
+		// set predictable config values
+		$test->ci_set_config(array(
+			'index_page'		=> 'index.php',
+			'base_url'			=> 'http://example.com/',
+			'subclass_prefix'	=> 'MY_'
+		));
+
+		$this->config = new $cls;	
+
+	}
+	
+	protected function _is_cli_request()
+	{
+		return FALSE;
+	}
+}
\ No newline at end of file
diff --git a/tests/mocks/database/.gitkeep b/tests/mocks/database/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/mocks/database/.gitkeep
diff --git a/tests/mocks/libraries/parser.php b/tests/mocks/libraries/parser.php
new file mode 100644
index 0000000..81dcfb3
--- /dev/null
+++ b/tests/mocks/libraries/parser.php
@@ -0,0 +1,3 @@
+<?php
+
+class Mock_Libraries_Parser extends CI_Parser {}
\ No newline at end of file
diff --git a/tests/mocks/libraries/table.php b/tests/mocks/libraries/table.php
new file mode 100644
index 0000000..1a6ff8d
--- /dev/null
+++ b/tests/mocks/libraries/table.php
@@ -0,0 +1,15 @@
+<?php
+
+class Mock_Libraries_Table extends CI_Table {
+	
+	// Overide inaccesible private or protected method
+	public function __call($method, $params)
+	{
+		if (is_callable(array($this, '_'.$method)))
+		{
+			return call_user_func_array(array($this, '_'.$method), $params);
+		}
+
+		throw new BadMethodCallException('Method '.$method.' was not found');
+	}
+}
\ No newline at end of file
diff --git a/tests/mocks/libraries/typography.php b/tests/mocks/libraries/typography.php
new file mode 100644
index 0000000..0f76c57
--- /dev/null
+++ b/tests/mocks/libraries/typography.php
@@ -0,0 +1,3 @@
+<?php
+
+class Mock_Libraries_Typography extends CI_Typography {}
\ No newline at end of file
diff --git a/tests/mocks/libraries/useragent.php b/tests/mocks/libraries/useragent.php
new file mode 100644
index 0000000..c957cde
--- /dev/null
+++ b/tests/mocks/libraries/useragent.php
@@ -0,0 +1,3 @@
+<?php
+
+class Mock_Libraries_UserAgent extends CI_User_agent {}
\ No newline at end of file