0

How do I mock the file_system service in PHPUnit?

The issue is being reproduced when \Drupal::service('file_system') is executing in the test suite environment. If \Drupal::service('file_system') is removed the class loads the assertions in the test class run perfectly. My belief is that this service needs to be mocked. (This could be completely false. I am really unsure).

The terminal error displayed when running the test is the following.

Drupal\Core\DependencyInjection\ContainerNotInitializedException: \Drupal::$container is not initialized yet. \Drupal::setContainer()

This is the class method that executes the Drupal 8 service.

 /**
   * @inheritdoc
   */
  public function setBasePath($path = Null) {

    if ($path !== Null) {
      $this->directories['base'] = $path;
    } else{
     $this->directories['base'] = \Drupal::service('file_system')->realpath(file_default_scheme() . "://");
    }
  }

This is the test class that is going to test the above class in the future. Right now it compares a string only.

/**
 *
 * @group react_forms
 */
class DirectoryStructureTest extends \Drupal\Tests\UnitTestCase {

  /**
   * @var object
   */
  private $objToTest;


  /**
   *
   */
  public function setUp() {
    $this->objToTest = new DirectoryStructure();
  }


  public function testGetDirectories() {

    $this->assertEquals('this', 'this');
  }


  /**
   * Once test method has finished running, whether it succeeded or failed,
   * tearDown() will be invoked. Unset the unit created object.
   */
  public function tearDown() {
    unset($this->objToTest);
  }
}

1 Answer 1

2

You shouldn't call file_system with \Drupal::service('file_system') use dependency injection instead:

So try something like the following in your service:

  1. Add arguments to your *.services.yml file.

services:
  yourModule.yourService:
    class: Drupal\yourModule\yourServiceClass
    arguments: ['@file_system']

  1. Inject the file_system service in your Class:

  use Drupal\Core\File\FileSystemInterface;

  /**
   * The file system service.
   * @var \Drupal\Core\File\FileSystemInterface
   */
  protected $fileSystem;
  /**
  * Class constructor.
  * @param \Drupal\Core\File\FileSystemInterface $file_system
  */
  public function __construct(FileSystemInterface $file_system) {;
    $this->fileSystem = $file_system;
  }

  1. Change setBasePath method to be like.

  /**
   * @inheritdoc
   */
  public function setBasePath($path = Null) {

    if ($path !== Null) {
      $this->directories['base'] = $path;
    } else{
     $this->directories['base'] = $this->fileSystem->realpath(file_default_scheme() . "://");
    }
  }

1
  • You are welcome, i'm glad that help.
    – berramou
    Commented Feb 25, 2019 at 8:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.