6

我想使用vfsstream

class MyClass{

  public function createFile($dirPath)
  {
    $name = time() . "-RT";
    $file = $dirPath . '/' . $name . '.tmp';

    fopen($file, "w+");
    if (file_exists($file)) {
        return $name . '.tmp';
    } else {
        return '';
    }
  }
}

但是当我尝试测试文件创建时:

$filename = $myClass->createFile(vfsStream::url('/var/www/app/web/exported/folder'));

我收到一个错误:

无法打开流:“org\bovigo\vfs\vfsStreamWrapper::stream_open”调用失败 fopen(vfs://var/www/app/web/exported/folder)

我看到这个问题在谈论模拟文件系统,但它没有关于文件创建的信息。vfsstream 是否支持使用 fopen 函数创建文件?如何测试文件创建?

4

2 回答 2

3

尝试使用设置创建 vsf 流,例如:

$root = vfsStream::setup('root');
$filename = $myClass->createFile($root->url());

希望这有帮助

作为工作示例:

/**
 * @test
 * @group unit
 */
public function itShouldBeTested()
{
    $myClass = new MyClass();

    $root = vfsStream::setup('root');
    $filename = $myClass->createFile($root->url());
    $this->assertNotNull($filename);
    var_dump($filename);
}

这将产生

(dev) bash-4.4$ phpunit -c app --filter=itShouldBeTested PHPUnit 4.8.26 由 Sebastian Bergmann 和贡献者编写。

.string(17) "1498555092-RT.tmp"

时间:13.11 秒,内存:200.00MB

好的(1 个测试,1 个断言)

于 2017-06-27T09:04:32.893 回答
0

OOP 方式是这样的:

interface FileClientInterface {
    function open($path);
    function exist($path);
}

class FileClient implements FileClientInterface {
    function open($path)
    {
        fopen($path, "w+");
    }

    function exist($path)
    {
        return file_exists($path);
    }
}

class MyClass
{
    private $fileClient;

    /**
     * MyClass constructor.
     * @param $fileClient
     */
    public function __construct(FileClientInterface $fileClient)
    {
        $this->fileClient = $fileClient;
    }

    public function createFile($dirPath)
    {
        $name = time() . "-RT";
        $file = $dirPath . '/' . $name . '.tmp';

        $this->fileClient->open($file);
        fopen($file, "w+");
        if ($this->fileClient->exist($file)) {
            return $name . '.tmp';
        } else {
            return '';
        }

    }
}

class MockFileClient implements FileClientInterface {
    public $calledOpen = 0;
    public $calledExists = 0;

    public function open($path)
    {
        $this->calledOpen ++;
    }

    public function exist($path)
    {
        $this->calledExists++;
    }

}


//not the test
$mockFileClient = new MockFileClient();
$myClass = new MyClass($mockFileClient);
$myClass->createFile('/test/path');

print_r($mockFileClient->calledOpen . PHP_EOL);
print_r($mockFileClient->calledExists . PHP_EOL);

所以我们正在创建一个接口(FileClientInterface)和两个实现类,一个用于生产,一个用于测试(一个带有模拟)。测试实现只是在调用它的方法时增加一个计数器。这样我们在测试中解耦了实际的 I/O 方法。

于 2017-06-27T09:21:47.880 回答