在一个项目中,我发现了这样的代码行:
protected function save($content, $path)
{
// ...
if (($handler = @fopen($path, 'w')) === false) {
throw new Exception('...');
}
// ...
if (@fwrite($handler, $content) === false) {
throw new Exception('...');
}
// ...
@fclose($handler);
}我想用PHPUnit测试这个方法,但是我有点被正确的测试用例困住了。如果我将传递不正确的$path或具有不正确权限的正确$path (例如0444),那么一切都将在第一个异常处停止。如果我通过了具有正确权限的正确的$path,也将能够写入文件,并且不会到达第二个异常。
那么,在不重写此方法的情况下,有什么方法可以测试第二个异常吗?
还是最好在一种情况下同时检查fopen和fwrite,并对两者只使用一个异常?
或者最好的选择是将这种方法分为两种--一种用于打开,另一种用于编写--并分别测试它们?
发布于 2016-02-12 13:29:46
实现目标的最佳方法是使用模拟的文件系统。我建议使用vfsStream
$ composer require mikey179/vfsStream首先,我要提到的是,fread只在使用无效参数调用此函数时才返回false。如果发生任何其他错误,它将返回已写入的字节数。因此,您必须添加另一个检查:
class SomeClass {
public function save($content, $path)
{
// ...
if (($handler = @fopen($path, 'w')) === false) {
throw new Exception('...');
}
$result = @fwrite($handler, $content);
// ...
if ($result === false) { // this will only happen when passing invalid arguments to fwrite
throw new Exception('...');
}
// ...
if ($result < strlen($content)) { // additional check if all bytes could have been written to disk
throw new Exception('...');
}
// ...
@fclose($handler);
}
}该方法的测试用例可能如下所示:
class SomeClassTest extends \PHPUnit_Framework_TestCase {
/**
* @var vfsStreamDirectory
*/
private $fs_mock;
/**
* @var vfsStreamFile
*/
private $file_mock;
/**
* @var $sut System under test
*/
private $sut;
public function setUp() {
$this->fs_mock = vfsStream::setup();
$this->file_mock = new vfsStreamFile('filename.ext');
$this->fs_mock->addChild($this->file_mock);
$this->sut = new SomeClass();
}
public function testSaveThrowsExceptionOnMissingWritePermissionOnFile() {
$this->expectException(\Exception::class);
$this->file_mock->chmod(0);
$this->sut->save(
'content',
$this->file_mock->url()
);
}
public function testSaveThrowsExceptionOnMissingWritePermissionOnDirectory() {
$this->expectException(\Exception::class);
$this->fs_mock->chmod(0);
$this->sut->save(
'content',
$this->fs_mock->url().'/new_file.ext'
);
}
public function testSaveThrowsExceptionOnInvalidContentType() {
$this->expectException(\Exception::class);
$this->fs_mock->chmod(0);
$this->sut->save(
$this,
$this->file_mock->url()
);
}
public function testSaveThrowsExceptionOnDiskFull() {
$this->expectException(\Exception::class);
$this->fs_mock->chmod(0777); // to be sure
$this->file_mock->chmod(0777); // to be sure
vfsStream::setQuota(1); // set disk quota to 1 byte
$this->sut->save(
'content',
$this->file_mock->url()
);
}
}我希望我能帮上忙。
https://stackoverflow.com/questions/35290479
复制相似问题