Recently I found myself needing to write tests for a small class that read from a json file. The class needed to read a json file, validate its existence and content, provide a method to inform the user if a certain key exists, and provide a method to retrieve a value for a given key. The class looked something like:
I’d like to write tests to validate that:
Testing this class in isolation can be tricky because it currently has a dependency on the file system. Storing test json files to test this class would work, but is not ideal because it leaves a dependency on the file system in your tests. As with any external resource, there might be intermittent problems with the file system and could result in some flaky tests.
This is where vfsStream shines. vfsStream is a stream wrapper for a virtual file system. Essentially it allows you to define a file system structure, and provides you a path that your tests will be able to read/write/manipulate files from. This makes testing code that uses the php native functions for file manipulation super easy! Here’s what my tests end up looking like.
In the above example, the setUp() method defines a directory structure to have a directory json with two files named valid.json and invalid.json with their content being provided. It then calls vfsStream::setup() which takes in a root directory name, permissions for the directory, and the defined directory array. The virtual file system is stored for reference within the tests. At any point in the tests you can call $file_system->url() which will return a full file path to the root directory in your file system, it’s output will look like vfs://root/. After all setup is done, tests can pass in their virtual file paths and native functions like file_get_contents() will read from your virtual file system.
I found this approach to be much cleaner as it removes the file system dependency, gives the developer full control on what their testing file system looks like, and does not require storing any test files your tests might need. I think it becomes even more valuable when your testing code that creates files or directories because there is no clean up required afterwards!