I'm curious about the best way of speccing classes that handle file operations.
Assuming I have a fictional class with a method duplicate
whose job is to duplicate the contents of a file.
<?php
class FileOperator
{
public function duplicate($filename)
{
$content = file_get_contents($filename);
file_put_contents($filename, $content.$content);
}
}
I know that I can use something like vfsStream to assert the change without touching the actual filesystem (at least with assertions in PHPUnit).
How could I assert that in a spec? Or would it be approached differently?
Also, I get that I might want to extract that functionality into another class and use a Spy to assert that the FileOperator calls its dependency correctly, but then I'd still have to spec that adapter class, and my question remains.
Thanks.
This is more likely a functional test rather than an unit test, so it's hard to use phpspec in this case.
If you insist, I see two options.
If you happen to need a method to fetch the file contents too, you could write your spec this way:
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use PhpSpec\ObjectBehavior;
class FileOperatorSpec extends ObjectBehavior
{
/**
* @var vfsStreamDirectory
*/
private $workDir;
function let()
{
$this->workDir = vfsStream::setup('workDir');
}
function it_duplicates_a_content_in_a_file()
{
$this->createFile('foo', 'bar');
$this->duplicate('vfs://workDir/foo');
$this->read('vfs://workDir/foo')->shouldReturn('barbar');
}
private function createFile($path, $content)
{
$file = vfsStream::newFile($path);
$file->setContent($content);
$this->workDir->addChild($file);
}
}
Alternatively, you could use the expect helper:
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use PhpSpec\ObjectBehavior;
class FileOperatorSpec extends ObjectBehavior
{
/**
* @var vfsStreamDirectory
*/
private $workDir;
function let()
{
$this->workDir = vfsStream::setup('workDir');
}
function it_duplicates_a_content_in_a_file()
{
$this->createFile('foo', 'bar');
$this->duplicate('vfs://workDir/foo');
expect(file_get_contents('vfs://workDir/foo'))->toBe('barbar');
}
private function createFile($path, $content)
{
$file = vfsStream::newFile($path);
$file->setContent($content);
$this->workDir->addChild($file);
}
}