{
    "href": "/post/2012/07/04/when-possible-use-file-resources-instead-of-file-names/",
    "relId": "2012/07/04/when-possible-use-file-resources-instead-of-file-names",
    "title": "When Possible, Use File *Resources* Instead Of File *Names*",
    "author": "pmjones",
    "markup": "html",
    "tags": [
        {
            "href": "/tag/aura/",
            "relId": "aura",
            "title": "Aura",
            "author": null,
            "created": "2020-09-14 21:51:57 UTC",
            "updated": [
                "2020-09-14 21:51:57 UTC"
            ],
            "markup": "markdown"
        },
        {
            "href": "/tag/php/",
            "relId": "php",
            "title": "PHP",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        },
        {
            "href": "/tag/programming/",
            "relId": "programming",
            "title": "Programming",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        }
    ],
    "created": "2012-07-04 15:05:26 UTC",
    "updated": [
        "2012-07-04 15:05:26 UTC"
    ],
    "html": "<p>In testing the <a href=\"https://github.com/auraphp/Aura.Http\">Aura.Http</a> package, I have realized that it's much more flexible, testing wise, to pass around file resources (a.k.a. handles, pointers, or streams) than it is to pass around file names.  When you do that, you can use a <code>php://memory</code> stream instead of attempting to touch the file system. For example:</p>\n<pre><code>&lt;?php\n// $this-&gt;save('/path/to/file.txt', 'Hello World!');\npublic function save($file, $data)\n{\n    file_put_contents($file, $data);\n}\n</code></pre>\n<p>The test would have to be something like this</p>\n<pre><code>&lt;?php\npublic function testSave()\n{\n    $file = '/path/to/file.txt';\n    $data = 'Hello World!';\n    $this-&gt;system_under_test-&gt;save($file, $data);\n    $this-&gt;assertTrue(file_exists($file));\n    $actual = file_get_contents($file);\n    $this-&gt;assertSame($data, $actual);\n    unlink($file);\n}\n</code></pre>\n<p>All sorts of things can go wrong with that, starting with file permissions. It's also against testing dogma, in that you touch the file system.</p>\n<p>However, if you rewrite the method to use a file <em>resource</em> instead of a file <em>name</em> ...</p>\n<pre><code>&lt;?php\n// $fp = fopen('/path/to/file.txt', 'w+');\n// $this-&gt;save($fp, 'Hello World!');\npublic function save($resource, $data)\n{\n    fwrite($resource, $data);\n}\n</code></pre>\n<p>This places control of the file creation in your hands directly, not under the control of the system under test.  Then the test looks like this (with a helper method):</p>\n<pre><code>&lt;?php\nprotected function readResource($resource)\n{\n    rewind($resource);\n    $data = null;\n    while (! feof($resource)) {\n        $data .= fread($resource, 8192);\n    }\n    return $data;\n}\n\npublic function testSave()\n{\n    $fp = fopen('php://memory');\n    $data = 'Hello World!';\n    $this-&gt;system_under_test-&gt;save($fp, $data);\n\n    $actual = $this-&gt;readResource($fp)\n    $this-&gt;assertSame($data, $actual);\n}\n</code></pre>\n<p>Voila! No more touching the file system.</p>\n<hr>\n<p class=\"reddit-links\">Read the Reddit discussion about this post <a href=\"https://www.reddit.com/r/PHP/comments/4j38rw/when_possible_use_file_resources_instead_of_file/\">here</a>.</p>\n"
}
