Skip to content

Commit

Permalink
Remove section on vfsStream
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed Mar 29, 2019
1 parent 771629a commit 196a9d8
Showing 1 changed file with 0 additions and 155 deletions.
155 changes: 0 additions & 155 deletions src/test-doubles.rst
Original file line number Diff line number Diff line change
Expand Up @@ -980,158 +980,3 @@ example, the web service described in :file:`GoogleSearch.wsdl`.
}
}
?>
.. _test-doubles.mocking-the-filesystem:

Mocking the Filesystem
######################

`vfsStream <https://github.com/mikey179/vfsStream>`_
is a `stream wrapper <http://www.php.net/streams>`_ for a
`virtual
filesystem <http://en.wikipedia.org/wiki/Virtual_file_system>`_ that may be helpful in unit tests to mock the real
filesystem.

Simply add a dependency on ``mikey179/vfsstream`` to your
project's ``composer.json`` file if you use
`Composer <https://getcomposer.org/>`_ to manage the
dependencies of your project. Here is a minimal example of a
``composer.json`` file that just defines a development-time
dependency on PHPUnit 4.6 and vfsStream:

.. code-block:: php
{
"require-dev": {
"phpunit/phpunit": "~4.6",
"mikey179/vfsstream": "~1"
}
}
:numref:`test-doubles.mocking-the-filesystem.examples.Example.php`
shows a class that interacts with the filesystem.

.. code-block:: php
:caption: A class that interacts with the filesystem
:name: test-doubles.mocking-the-filesystem.examples.Example.php
<?php
use PHPUnit\Framework\TestCase;
class Example
{
protected $id;
protected $directory;
public function __construct($id)
{
$this->id = $id;
}
public function setDirectory($directory)
{
$this->directory = $directory . DIRECTORY_SEPARATOR . $this->id;
if (!file_exists($this->directory)) {
mkdir($this->directory, 0700, true);
}
}
}?>
Without a virtual filesystem such as vfsStream we cannot test the
``setDirectory()`` method in isolation from external
influence (see :numref:`test-doubles.mocking-the-filesystem.examples.ExampleTest.php`).

.. code-block:: php
:caption: Testing a class that interacts with the filesystem
:name: test-doubles.mocking-the-filesystem.examples.ExampleTest.php
<?php
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase
{
protected function setUp()
{
if (file_exists(dirname(__FILE__) . '/id')) {
rmdir(dirname(__FILE__) . '/id');
}
}
public function testDirectoryIsCreated()
{
$example = new Example('id');
$this->assertFalse(file_exists(dirname(__FILE__) . '/id'));
$example->setDirectory(dirname(__FILE__));
$this->assertTrue(file_exists(dirname(__FILE__) . '/id'));
}
protected function tearDown()
{
if (file_exists(dirname(__FILE__) . '/id')) {
rmdir(dirname(__FILE__) . '/id');
}
}
}
?>
The approach above has several drawbacks:

-

As with any external resource, there might be intermittent problems with the filesystem. This makes tests interacting with it flaky.

-

In the ``setUp()`` and ``tearDown()`` methods we have to ensure that the directory does not exist before and after the test.

-

When the test execution terminates before the ``tearDown()`` method is invoked the directory will stay in the filesystem.

:numref:`test-doubles.mocking-the-filesystem.examples.ExampleTest2.php`
shows how vfsStream can be used to mock the filesystem in a test for a
class that interacts with the filesystem.

.. code-block:: php
:caption: Mocking the filesystem in a test for a class that interacts with the filesystem
:name: test-doubles.mocking-the-filesystem.examples.ExampleTest2.php
<?php
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase
{
public function setUp()
{
vfsStreamWrapper::register();
vfsStreamWrapper::setRoot(new vfsStreamDirectory('exampleDir'));
}
public function testDirectoryIsCreated()
{
$example = new Example('id');
$this->assertFalse(vfsStreamWrapper::getRoot()->hasChild('id'));
$example->setDirectory(vfsStream::url('exampleDir'));
$this->assertTrue(vfsStreamWrapper::getRoot()->hasChild('id'));
}
}
?>
This has several advantages:

-

The test itself is more concise.

-

vfsStream gives the test developer full control over what the filesystem environment looks like to the tested code.

-

Since the filesystem operations do not operate on the real filesystem anymore, cleanup operations in a ``tearDown()`` method are no longer required.


0 comments on commit 196a9d8

Please sign in to comment.