5

I'm new to OOP concepts, also PHPUnit Testing is new for me. I want to get the configuration in my testcase.

XYZFormResult.php

namespace Drupal\xyz\XYZFormResult;

use Drupal\Core\Config\ConfigFactory;
use Drupal\webform\Entity\WebformSubmission;

/**
* Class XYZFormResult.
*
* @package Drupal\xyz\formgroup
*/
class XYZFormResult {

    /**
    * Defines the immutable configuration object.
    *
    * @var \Drupal\Core\Config\Config|\Drupal\Core\Config\ImmutableConfig
    */
    private $config;

    /**
    * XYZFormResult constructor.
    *
    * @param \Drupal\Core\Config\ConfigFactory $config
    *   Inject ConfigFactory.
    */
    public function __construct(ConfigFactory $config) {
        $this->config = $config->getEditable('xyz.settings');
    }
}

XYZFormTest.php

namespace Drupal\Tests\xyz\Unit\XYZFormTest;

//use Drupal\Core\Config\ConfigFactory;
use Drupal\Tests\UnitTestCase;
use Drupal\xyz\formgroup\FormsGroupResult;
use Drupal\xyz\formgroup\XYZFormResult;
use Drupal\webform\Entity\WebformSubmission;


/**
* @coversDefaultClass \Drupal\xyz\formgroup\FormsGroupResult
* @group xyz
*/
class XYZFormTest extends UnitTestCase {
    /**
    *
    * @var \Drupal\Core\Config\ConfigFactory|\PHPUnit_Framework_MockObject_MockBuilder
    */
    protected $config;

    public function testxyz() {
        $this->XYZresult = new XYZFormResult($config);
    }
}

When I execute this XYZFormTest testcase, I need to pass a parameter for XYZFormResult(), how to pass config parameter?

If I pass any string in XYZFormResult(), I'm getting error this error:

__construct() must be an instance of Drupal\Core\Config\ConfigFactory, string given error
1
  • finally how do you solve the problem? Commented Mar 13, 2019 at 14:25

4 Answers 4

2

If you are using KernelTestBase (for "functional" tests that run on a bootstrapped Drupal and can use services), then you can use something the following:

class MyTest extends KernelTestBase {

  /**
   * Modules to enable.
   *
   * @var array
   */
  public static $modules = [
    'my_module',
  ];

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();

    // Set up our custom test config.
    $config = $this->config('my_module.settings');
    $config->set('my_setting_key', 'My setting value.');
    $config->save();
  }

  public function testMyThing() {
    // This config will be available in any service or place the config.factory
    // is injected as a dependency. Example:
    $config = $this->container->get('config.factory')->get('my_module.settings');
    $settingValue = $config->get('my_setting_key');
  }

}

A note: For this config to be usable, it needs to be defined in your module's schema at my_module/config/schema/my_module.schema.yml:

my_module.settings:
  type: config_object
  label: 'My Module settings'
  mapping:
    my_setting_key:
      type: string
      label: 'My Setting'
2

On a unit test, you can use getConfigFactoryStub():

namespace Drupal\Tests\my_module\Unit;

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Tests\UnitTestCase;

class MyModuleTest extends UnitTestCase {
  public function setUp() {
    parent::setUp();

    $config_map = [
      'my_module.settings' => [
        'setting_1' => 'value_1',
      ],
    ];

    // Get a stub for the config.factory service.
    $this->my_config_factory = $this->getConfigFactoryStub($config_map);

    $container = new ContainerBuilder();
    // Set the config.factory in the container also.
    $container->set('config.factory', $this->my_config_factory);

    \Drupal::setContainer($container);
  }

  public function testSomething() {
    $obj = new Something($this->my_config_factory);
    // ... asserts, etc.
}
}
1

You have the mock the dependencies. You can have a further look here.

Personally am using Prophecy for almost everything now, I like it better. In your case it would look like:

$config_prophecy = $this->prophesize(ConfigFactoryInterface::class);
$config_prophecy->getEditable('xyz.settings')->willReturn(['something'])->shouldBeCalled();
$this->XYZresult = new XYZFormResult($config_prophecy->reveal());

This says:

  1. You make your mock look like the config factory interface.
  2. You say that the 'getEditable' method is expected to call with the argument above and will return the data above.
  3. Then you inject this dependency, but you must "reveal" it, means that it's translated into an implementation of the ConfigFactoryInterface.

The good thing about prophecies that if you put them in instance variables then you even if you injected it in the setup of your unit test you can change them anytime later on, which helps you to imitate the desirable behaviour of your dependency in a use case.

1

You need to mock your object. There is a good guide on how to create tests at Drupalize.me (is not free).

// Config factory mock.
$config_factory = $this->createMock('Drupal\Core\Config\ConfigFactoryInterface');
// Mocking getEditable method.
$config_factory->expects($this->any())
      ->method('getEditable')
      ->with('xyz.settings')
      ->willReturn($config);

$this->XYZresult = new XYZFormResult($config_factory);

This technique is named test double and you can read more about it at http://softpixel.com/~mradcliffe/files/dcp2016-mocking-drupal.pdf

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.