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()
        );
    }
}