首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >fopen/fopen链的PHPUnit测试

fopen/fopen链的PHPUnit测试
EN

Stack Overflow用户
提问于 2016-02-09 11:10:02
回答 1查看 4K关注 0票数 2

在一个项目中,我发现了这样的代码行:

代码语言:javascript
复制
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,也将能够写入文件,并且不会到达第二个异常。

那么,在不重写此方法的情况下,有什么方法可以测试第二个异常吗?

还是最好在一种情况下同时检查fopenfwrite,并对两者只使用一个异常?

或者最好的选择是将这种方法分为两种--一种用于打开,另一种用于编写--并分别测试它们?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-12 13:29:46

实现目标的最佳方法是使用模拟的文件系统。我建议使用vfsStream

代码语言:javascript
复制
$ composer require mikey179/vfsStream

首先,我要提到的是,fread只在使用无效参数调用此函数时才返回false。如果发生任何其他错误,它将返回已写入的字节数。因此,您必须添加另一个检查:

代码语言:javascript
复制
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);
    }
}

该方法的测试用例可能如下所示:

代码语言:javascript
复制
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()
        );
    }
}

我希望我能帮上忙。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35290479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档