我试图减少程序的依赖性并使其更易于测试。我在一个类的__construct()
方法中进行了这样的实例。以前,它需要输入文件名,然后__construct()
方法会使用file_get_contents()
函数读取该文件名的内容并将其保存到属性中:
public function __construct($name){
$this->name = $name;
$this->contents = file_get_contents($name);
}
为了减少对文件系统的依赖,我将其替换为:
public function __construct(SplFileObject $file){
$this->name = $file->getFilename();
$this->contents = '';
while(!$file->eof()){
$this->contents .= $file->fgets();
}
}
我认为这种方法更容易进行测试,因为可以模拟一个 SplFileObject
(可以设置为包含任何想要的内容)并将其传递进去。到目前为止,我看到的示例都会采取以下做法:
$stub = $this->getMock('SplFileObject');
$stub->expects($this->any())
->method('fgets')
->will($this->returnValue('contents of file'));
然而,
SplFileObject
的模拟方法fgets
需要更复杂一些——它需要遍历内容的每一行,并在到达结尾时停止。
目前我有一个可行的解决方案——我刚刚创建了一个全新的类MockSplFileObject
,覆盖了这些方法:
class MockSplFileObject extends SplFileObject{
public $maxLines;
public $filename;
public $contents;
public $currentLine = 1;
public function __construct($filename, $contents){
$this->filename = $filename;
$this->contents = explode("\n",$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."\n";
}
public function getFilename(){
return $this->filename;
}
}
我用这种方法代替了调用PHPUnit的getMock()
函数。我的问题是:这种做法合理吗?或者有更好的模拟更复杂方法的方式吗?
$this->getMockBuilder('SplFileObject')->setConstructorArgs(['php://memory'])->getMock();
- Aine