Skip to content
Advertisement

PhpUnit: how to fake an outdated file?

I have a method in a class, which checks if a file is older than a day. It achieves this by getting the last change date of the file and comparing it with “now”:

    private function checkFileOutdated(string $filePath): bool
    {
        if (file_exists($filePath)) {
            $fileTimeStamp = filectime($filePath);

            $now = new DateTimeImmutable();
            $fileDate = new DateTimeImmutable('@' . $fileTimeStamp);
            $diff = (int) $now->format('Ymd') - (int) $fileDate->format('Ymd');

            return $diff > 0;
        }

        return true;
    }

I want to write a Unittest faking an outdated file. I tried to change the file date with touch:

        $location = '/var/www/var/xls/myfile.xlsx';
        $handle = fopen($location, 'wb');
        fclose($handle);
        exec('touch -a -m -t 202109231158 ' . $location);
        exec('ls -hl ' . $location, $output);
        var_dump($output);

The output gives me the information that in fact my file is from “Sep 23 11:58”, Yeay…..

But my test is failing and when I debug my file date is today and not September, the 23rd.

Using filemtime results in the same.

Is it possible to fake a file timestamp?

My system runs on an alpine linux.

Advertisement

Answer

Note you don’t have to create the file first, because touch does that for you. And there is a PHP built-in for touch(), you don’t have to shell exec:

touch('/tmp/foo', strtotime('-1 day'));
echo date('r', fileatime('/tmp/foo')), "n";
echo date('r', filectime('/tmp/foo')), "n";
echo date('r', filemtime('/tmp/foo')), "n";

This yields:

Tue, 02 Nov 2021 12:18:17 -0400
Wed, 03 Nov 2021 12:18:17 -0400
Tue, 02 Nov 2021 12:18:17 -0400

Applying your code but with filemtime:

$fileTimeStamp = filemtime($filePath);
$now = new DateTimeImmutable();
$fileDate = new DateTimeImmutable('@' . $fileTimeStamp);
$diff = (int) $now->format('Ymd') - (int) $fileDate->format('Ymd');
var_dump($diff);

Yields the desired truthy value:

1

However, this is a rather roundabout comparison. I’d just compare the timestamp values directly:

return filemtime('/tmp/foo') <= strtotime('-1 day');
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement