Testing code that reads and writes files usually ends in a tests/tmp directory, a setUp that creates it, a tearDown that recursively deletes it, and a suite that leaves the directory behind whenever something fatals halfway through. vfsStream registers a stream wrapper, so vfs:// paths behave like a filesystem that exists in memory for the length of one test.
use orgbovigovfsvfsStream;
class ConfigLoaderTest extends PHPUnit_Framework_TestCase
{
private $root;
public function setUp()
{
$this->root = vfsStream::setup('etc', null, array(
'app.ini' => "[db]nhost = 127.0.0.1n",
'app.ini.dist' => "[db]nhost = localhostn",
));
}
public function testPrefersTheLocalFileOverTheDistributedOne()
{
$loader = new ConfigLoader(vfsStream::url('etc'));
$this->assertSame('127.0.0.1', $loader->get('db.host'));
}
public function testReportsAnUnreadableFile()
{
$this->root->getChild('app.ini')->chmod(0000);
$this->setExpectedException('ConfigUnreadable');
new ConfigLoader(vfsStream::url('etc'));
}
}
The gain is not speed, though it is faster. It is that nothing survives the test: no directory to clean up, no permissions to arrange on a build server, and no chance of one test seeing a file another test forgot to remove. The second method is the part that is hard to do any other way — chmod(0000) inside a virtual filesystem reproduces an unreadable file without needing a real one and without running as a second user, and vfsStream::setQuota() does the same for a disk that is full. What it cannot do is anything that bypasses the stream wrapper: realpath(), glob() and most of the exec family either ignore vfs:// or behave differently on it, so code that shells out to mv still needs a real directory.