对文件系统进行模仿

最后更新于:2022-04-01 03:46:00

# 对文件系统进行模仿 [vfsStream](https://github.com/mikey179/vfsStream) 是对[虚拟文件系统](http://en.wikipedia.org/wiki/Virtual_file_system) 的 [流包覆器(stream wrapper)](http://www.php.net/streams),可以用于模仿真实文件系统,在单元测试中可能会有所助益。 如果使用 [Composer](https://getcomposer.org/) 来管理项目的依赖关系,那么只需简单的在项目的 `composer.json` 文件中加一条对 `mikey179/vfsStream` 的依赖关系即可。以下是一个最小化的 `composer.json`文件例子,只定义了一条对 PHPUnit 4.6 与 vfsStream 的开发时(development-time)依赖: ~~~ { "require-dev": { "phpunit/phpunit": "~4.6", "mikey179/vfsStream": "~1" } } ~~~ [Example 9.21, “一个与文件系统交互的类”](# "Example 9.21. 一个与文件系统交互的类")展示了一个与文件系统交互的类。 **Example 9.21. 一个与文件系统交互的类** ~~~ <?php class Example { protected $id; protected $directory; public function __construct($id) { $this->id = $id; } public function setDirectory($directory) { $this->directory = $directory . DIRECTORY_SEPARATOR . $this->id; if (!file_exists($this->directory)) { mkdir($this->directory, 0700, TRUE); } } }?> ~~~ 如果不使用诸如 vfsStream 这样的虚拟文件系统,就无法在隔离外部影响的情况下对 `setDirectory()` 方法进行测试(参见 [Example 9.22, “对一个与文件系统交互的类进行测试”](# "Example 9.22. 对一个与文件系统交互的类进行测试"))。 **Example 9.22. 对一个与文件系统交互的类进行测试** ~~~ <?php require_once 'Example.php'; class ExampleTest extends PHPUnit_Framework_TestCase { protected function setUp() { if (file_exists(dirname(__FILE__) . '/id')) { rmdir(dirname(__FILE__) . '/id'); } } public function testDirectoryIsCreated() { $example = new Example('id'); $this->assertFalse(file_exists(dirname(__FILE__) . '/id')); $example->setDirectory(dirname(__FILE__)); $this->assertTrue(file_exists(dirname(__FILE__) . '/id')); } protected function tearDown() { if (file_exists(dirname(__FILE__) . '/id')) { rmdir(dirname(__FILE__) . '/id'); } } } ?> ~~~ 上面的方法有几个缺点: - 和任何其他外部资源一样,文件系统可能会间歇性的出现一些问题,这使得和它交互的测试变得不可靠。 - 在 `setUp()` 和 `tearDown()` 方法中,必须确保这个目录在测试前和测试后均不存在。 - 如果测试在 `tearDown()` 方法被调用之前就终止了,这个目录就会遗留在文件系统中。 [Example 9.23, “在对与文件系统交互的类进行的测试中模仿文件系统”](# "Example 9.23. 在对与文件系统交互的类进行的测试中模仿文件系统")展示了如何在对与文件系统交互的类进行的测试中使用 vfsStream 来模仿文件系统。 **Example 9.23. 在对与文件系统交互的类进行的测试中模仿文件系统** ~~~ <?php require_once 'vfsStream/vfsStream.php'; require_once 'Example.php'; class ExampleTest extends PHPUnit_Framework_TestCase { public function setUp() { vfsStreamWrapper::register(); vfsStreamWrapper::setRoot(new vfsStreamDirectory('exampleDir')); } public function testDirectoryIsCreated() { $example = new Example('id'); $this->assertFalse(vfsStreamWrapper::getRoot()->hasChild('id')); $example->setDirectory(vfsStream::url('exampleDir')); $this->assertTrue(vfsStreamWrapper::getRoot()->hasChild('id')); } } ?> ~~~ 这有几个优点: - 测试本身更加简洁。 - vfsStream 让开发者能够完全控制被测代码所处的文件系统环境。 - 由于文件系统操作不再对真实文件系统进行操作,`tearDown()` 方法中的清理操作不再需要了。
';