2 minutes
Testing Legacy Code: Filesystem Interaction
This is the third article in the series of Testing Legacy Code. Check out the first part Testing Legacy Code: Echo Output in which I provide information about the origin of these examples.
vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with any unit test framework, like PHPUnit or SimpleTest.
https://github.com/bovigo/vfsStream
Function with filesystem interaction
Given is a method which increments the counter persisted in the local filesystem.
<?php
declare(strict_types=1);
namespace RefactoringLegacyCode;
use function file_get_contents;
use function file_put_contents;
class FilesystemInteraction
{
    public function countHit(): void
    {
        $count = file_get_contents(__DIR__ . '/hit_counter.txt');
        file_put_contents(__DIR__ . '/hit_counter.txt', ++$count);
    }
}
Before writing a test for it, a change to inject the dependency is required.
<?php
declare(strict_types=1);
namespace RefactoringLegacyCode;
use function file_get_contents;
use function file_put_contents;
class FilesystemInteraction
{
    public function countHit(string $file = __DIR__ . '/hit_counter.txt'): void
    {
        $count = file_get_contents($file);
        file_put_contents($file, ++$count);
    }
}
Test
With the changed method, vfsStream can now be utilized to inject a virtual file for testing.
<?php
declare(strict_types=1);
namespace RefactoringLegacyCodeTest;
use org\bovigo\vfs\vfsStream;
use PHPUnit\Framework\TestCase;
use RefactoringLegacyCode\FilesystemInteraction;
class FilesystemInteractionTest extends TestCase
{
    /**
     * @covers \RefactoringLegacyCode\FilesystemInteraction::countHit
     */
    public function test_countHit(): void
    {
        $vfs = vfsStream::setup();
        $hitCounterFile = vfsStream::newFile('test_hit_counter.txt')
            ->at($vfs)
            ->setContent('1337');
        $filesystemInteraction = new FilesystemInteraction();
        $filesystemInteraction->countHit($hitCounterFile->url());
        self::assertSame(
            '1338',
            $hitCounterFile->getContent()
        );
    }
}
            Read other posts