Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics

Dashboard
Notifications
Mark all as read
Q&A

Mocking tempnam() with vfsstream

+2
−1

How do I mock tempnam() with vfsStream for code that uses it to create temporary files (for example, in a PHPUnit test)?

Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

0 comments

1 answer

+1
−0

This turned out to be a more difficult question to address than I initially thought! After many attempts at finding a way to use tempnam() with vfsStream, I only just now found out from the vfsStream documentation that tempnam() is one of those types of functions that is among the "thin wrappers around the native C functions". These types of functions evidently do not support "stream wrappers like vfs" (from the documentation).

Thus, it does not appear that you can use vfsStream with the tempnam() function.

I don't know if mocking tempnam() using another tool like PHP-Mock would help for your situation. Here is a possible example of what mocking tempnam() with PHP-Mock could look like, though.

mock.php

<?php

namespace example;

# ref: https://getcomposer.org/doc/01-basic-usage.md
require __DIR__ . '/vendor/autoload.php';
# ref: https://github.com/php-mock/php-mock#php-mock-api
use phpmock\MockBuilder;

$builder = new MockBuilder();
$builder->setNamespace(__NAMESPACE__)
        ->setName("tempnam")
        ->setFunction(
            function() {
                return '/tmp/file_abc';
            }
        );
$mock = $builder->build();
$mock->enable();

echo(assert(tempnam() == '/tmp/file_abc'));
// result should be 1

composer.json

{
    "require-dev": {
        "php-mock/php-mock": "^2.3"
    }
}

For reference, the code that I was using earlier when trying to find a method to use vfsStream with tempnam() looked like this:

Example.php

<?php

#ref: https://github.com/bovigo/vfsStream/wiki/Example
#ref: https://www.php.net/manual/en/function.tempnam.php

namespace Example;

class Example
{
    public function __construct()
    {
    }

    public function addFile($directory, $filename)
    {
        $tmpfname = tempnam($directory, $filename);
        $handle = fopen($tmpfname, "w");
        fwrite($handle, "Hello, world in a file!");
        fclose($handle);
    }
}

ExampleTest.php

<?php

# ref: https://github.com/bovigo/vfsStream/wiki/Example

namespace Example;

require_once 'Example.php';
use PHPUnit\Framework\TestCase;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;

class ExampleTest extends TestCase
{
    private $testDirectory;

    public function setUp(): void
    {
        $this->testDirectory = vfsStream::setup('test_directory');
    }

    public function testFileIsAdded()
    {
        $e = new Example();
        $e->addFile(vfsStream::url('test_directory'), 'test_file');
        $this->assertTrue($this->testDirectory->hasChild('test_file'));
    }
}

composer.json

{
    "require": {
        "mikey179/vfsstream": "^1.6"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.5"
    }
}

And when running the ExampleTest.php file, the result was this (with username omitted):

$ vendor/phpunit/phpunit/phpunit ExampleTest.php
PHPUnit 9.5.2 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)

Time: 00:00.027, Memory: 4.00 MB

There was 1 error:

1) Example\ExampleTest::testFileIsAdded
tempnam(): file created in the system's temporary directory

/home/username/programming/q8/Example.php:16
/home/username/programming/q8/ExampleTest.php:24

ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
Why does this post require moderator attention?
You might want to add some details to your flag.

0 comments

Sign up to answer this question »