I'm trying to reduce the dependencies of my program and make it more easily testable. One instance where I did this is in the __construct()
method of one of my classes. Before, it used to take in a file name and then the __construct()
method would use file_get_contents()
on that filename to save the contents into a property:
public function __construct($name){
$this->name = $name;
$this->contents = file_get_contents($name);
}
To reduce dependency on the filesystem I replaced this with:
public function __construct(SplFileObject $file){
$this->name = $file->getFilename();
$this->contents = '';
while(!$file->eof()){
$this->contents .= $file->fgets();
}
}
I believe that this is more easily testable, since I can mock up an SplFileObject
(which could be set to contain whatever content I want) and pass it in. The examples I have seen so far involve doing something like this:
$stub = $this->getMock('SplFileObject');
$stub->expects($this->any())
->method('fgets')
->will($this->returnValue('contents of file'));
However the mock fgets
method of the SplFileObject
will need to be more complicated - it needs to loop through each line of the contents, and stop when it has reached the end.
For the time being I have a solution that works - I just created an entirely new class called MockSplFileObject
which overrides these methods:
class MockSplFileObject extends SplFileObject{
public $maxLines;
public $filename;
public $contents;
public $currentLine = 1;
public function __construct($filename, $contents){
$this->filename = $filename;
$this->contents = explode("
",$contents);
return true;
}
public function eof(){
if($this->currentLine == count($this->contents)+1){
return true;
}
return false;
}
public function fgets(){
$line = $this->contents[$this->currentLine-1];
$this->currentLine++;
return $line."
";
}
public function getFilename(){
return $this->filename;
}
}
I then use this instead of calling PHPUnit's getMock()
function. My question is: is this a legitimate way of doing things? Or is there a better way of mocking up more complex methods?