I have a custom Lightweight PHP framework that our company uses. To start, I don't want the suggestion to use a third-party framework. I am trying to write unit tests for it but I have stumbled upon a problem. I am relatively new to unit testing, but most of the code is already covered.
I have a loader class that will require files that can't be loaded with a class auto loader (e.g. Configuration files). It has a kind of fallback system where if you don't specify a module to load a particular resource from, it will try to guess based on the current module, then the default module. This has required me (so far as I can see) to check for the existence of a particular file before falling back to the default.
The problem I'm running into is writing a test for the class that doesn't actually depend on any files existing (which is obviously desirable). I've read about virtual file systems and testing, but I'm having trouble seeing how I can utilize it to solve my problem.
I can write an abstraction of the filesystem that I inject into this class, but then that class will have a similar problem.
In pseudo code: if file exists in this module, load it; if not, load the default.
Any suggestions are greatly appreciated.
EDIT:
Here's an excerpt of the code:
class Base implements Loader {
...
protected function _include( $type, $name ){
$identifier = $this->parseName($name);
$path = '/'.$this->resource_types[$type]['directory'].'/'.$this->resource_types[$type]['file_prefix'].$identifier['name'].'.php';
if( $identifier['module'] && is_file(Core::basePath().'/'.Constant::get('MODULE_PATH').'/'.$identifier['module'].$path) ){
Core::requireRoot('/'.Constant::get('MODULE_PATH').'/'.$identifier['module'].$path);
} else if( is_file(Core::basePath().'/'.Constant::get('CORE_PATH').$path) ){
Core::requireRoot('/'.Constant::get('CORE_PATH').$path);
} else {
throw new Exceptions\Load(ucwords($type).' '.$name.' not found');
}
}
....
}
This is a very low-level class, so it has a few static calls that are basically substitutes for or wrappers around native PHP functions. Core::requireRoot is just a wrapper around the native require function. Constant::get is a custom implementation of constants (an alternative to define, then using the constant directly). Keep in mind I'm not actually testing this method directly. I have public methods such as loadHooks that I am actually testing that call this method behind the scenes.
Configclass which you inject into the code, and the code uses$config->get('foo.bar')to load those files. That's easily mockable. A hardcodedfopen('config/foo/bar')is virtually impossible to mock.