test_helpers-1.0.0-alpha6/tests/src/Unit/TestHelpersApi/ServicesTest.php
tests/src/Unit/TestHelpersApi/ServicesTest.php
<?php
declare(strict_types=1);
namespace Drupal\Tests\test_helpers\Unit\TestHelpersApi;
use Drupal\Core\Entity\Controller\EntityController;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\UrlGenerator;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Tests\UnitTestCase;
use Drupal\language\ConfigurableLanguageManagerInterface;
use Drupal\language\LanguageNegotiationMethodManager;
use Drupal\media\Plugin\Derivative\DynamicLocalTasks;
use Drupal\test_helpers\TestHelpers;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversMethod;
use PHPUnit\Framework\Attributes\Group;
/**
* Tests Query helper functions.
*/
#[CoversClass(TestHelpers::class)]
#[Group('test_helpers')]
#[CoversMethod(TestHelpers::class, 'service')]
#[CoversMethod(TestHelpers::class, 'setServices')]
#[CoversMethod(TestHelpers::class, 'createClass')]
#[CoversMethod(TestHelpers::class, 'initServiceFromYaml')]
#[CoversMethod(TestHelpers::class, 'initService')]
#[CoversMethod(TestHelpers::class, 'initEntityTypeManagerStubs')]
class ServicesTest extends UnitTestCase {
use StringTranslationTrait;
/**
* Tests the service() and setServices() methods.
*/
public function testServices() {
/** @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit\Framework\MockObject\MockObject $entityType */
$entityType = $this->createMock(EntityTypeInterface::class);
$entityType->method('getSingularLabel')->willReturn('my entity');
/** @var \Drupal\Core\Entity\EntityTypeManagerInterface|\PHPUnit\Framework\MockObject\MockObject $entityTypeManager */
$entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
$entityTypeManager->method('getDefinition')->willReturn($entityType);
TestHelpers::service('string_translation');
TestHelpers::setServices([
'url_generator' => UrlGenerator::class,
]);
// Checking initialized services.
try {
$service = TestHelpers::createClass(EntityController::class);
$this->fail("Expected ServiceNotFoundException is not thrown.");
}
catch (ServiceNotFoundException $e) {
$this->assertEquals('You have requested a non-existent service "entity_type.manager".', $e->getMessage());
}
TestHelpers::setServices([
'entity_type.bundle.info' => NULL,
'renderer' => NULL,
'entity_type.manager' => $entityTypeManager,
'entity.repository' => NULL,
'current_route_match' => NULL,
]);
// Testing the behavior on a real service with the 'create' function.
$service = TestHelpers::createClass(EntityController::class);
$result = $service->addTitle('my_entity');
$this->assertSame('Add my entity', $result->__toString());
// Checking resetting of the container.
TestHelpers::setServices(['entity.repository'], TRUE);
try {
$service = TestHelpers::createClass(EntityController::class);
$this->fail('Previous line should throw an exception.');
}
catch (ServiceNotFoundException $e) {
$this->assertStringStartsWith('You have requested a non-existent service', $e->getMessage());
}
/* Testing services initialization. */
// Resetting the container to have a clear environment.
TestHelpers::getContainer(TRUE);
// With no initialization flag here should be a mock that always return
// NULL.
TestHelpers::service('module_handler', NULL, NULL, NULL, NULL, FALSE);
$this->assertNull(\Drupal::service('module_handler')->getModuleList());
// With the initialization flag here should be a real initialized object.
TestHelpers::service('module_handler', NULL, TRUE, NULL, NULL, TRUE);
$this->assertIsArray(\Drupal::service('module_handler')->getModuleList());
// With the initialization flag equals FALSE the auto initialized services
// should return NULL always.
TestHelpers::service('string_translation', NULL, TRUE, NULL, NULL, FALSE);
$this->assertNull(\Drupal::service('string_translation')->translate('foo'));
}
/**
* Tests the service() and setServices() methods.
*/
public function testServiceMocked() {
$testClass = $this;
TestHelpers::service('string_translation');
$renderer = TestHelpers::service('renderer', NULL, NULL, NULL, NULL, FALSE);
// The classical approach.
$renderer->method('render')->willReturnCallback(function (array &$element) {
// We can't get access to `$this` keyword here, because PHPUnit approach
// executes the callback function in the unit test context, not in the
// service's class (Renderer).
/* $this->replacePlaceholders($element); */
return [
'#markup' => $this->t('Element @title', [
'@title' => $element['#title'],
]),
];
});
// The modern approaches.
// Using the setPrivateProperty() we can set values for any private or
// protected property.
$rendererConfig = ['foo' => 'bar'];
TestHelpers::setPrivateProperty($renderer, 'rendererConfig', $rendererConfig);
TestHelpers::setMockedClassMethod($renderer, 'renderRoot',
function (array &$element) use ($testClass) {
// Using the setMockedClassMethod() we can get access to `$this` keyword
// with any private and protected properties and methods.
/** @var \Drupal\Core\Render\Renderer $this */
// @phpstan-ignore-next-line This will be executed in the class context.
$this->replacePlaceholders($element);
return [
'#markup' => TestHelpers::callPrivateMethod($testClass, 't', [
'Root for @title with @theme', [
'@title' => $element['#title'],
'@theme' => 'My theme',
],
]),
];
});
$element = ['#title' => 'My Element'];
$this->assertEquals('Element My Element', (string) \Drupal::service('renderer')->render($element)['#markup']);
$this->assertEquals('Root for My Element with My theme', (string) \Drupal::service('renderer')->renderRoot($element)['#markup']);
}
/**
* Tests the service() and setServices() methods.
*/
public function testInitServiceFromYaml() {
TestHelpers::service('plugin.manager.language_negotiation_method', $this->createMock(LanguageNegotiationMethodManager::class));
\Drupal::service('plugin.manager.language_negotiation_method')
->method('getDefinitions')
->willReturn(['method1', 'method2']);
TestHelpers::setServices([
'config.factory' => NULL,
'language_manager' => $this->createMock(ConfigurableLanguageManagerInterface::class),
'settings' => NULL,
'request_stack' => NULL,
]);
$service = TestHelpers::initServiceFromYaml(
'core/modules/language/language.services.yml',
'language_negotiator');
$this->assertEquals(['method1', 'method2'], $service->getNegotiationMethods());
// Testing initialization of a service with null argument.
// @see https://www.drupal.org/project/test_helpers/issues/3378437
TestHelpers::initServiceFromYaml(
'core/core.services.yml',
'transliteration');
}
/**
* Tests the service() and setServices() methods.
*/
public function testInitService() {
$service = TestHelpers::initService(LanguageNegotiationMethodManager::class);
$this->assertInstanceOf(LanguageNegotiationMethodManager::class, $service);
$service = TestHelpers::initService(LanguageNegotiationMethodManager::class, 'plugin.manager.language_negotiation_method');
$this->assertInstanceOf(LanguageNegotiationMethodManager::class, $service);
try {
$service = TestHelpers::initService(LanguageNegotiationMethodManager::class, 'wrong_service_name');
$this->fail('Previous line should throw an exception.');
}
catch (\Exception $e) {
$this->assertStringStartsWith("The service name 'plugin.manager.language_negotiation_method' differs from required name 'wrong_service_name'", $e->getMessage());
}
// The case with the service name as an argument is tested in the
// Drupal\Tests\test_helpers_example\Unit\ConfigEventsSubscriberTest()
// because it requires a 'services.yml' file to be pre-send, but for this
// module it is not needed.
}
/**
* Creates a class instance with the given parameters.
*/
public function testCreateClass() {
TestHelpers::setServices([
'string_translation',
'entity_type.manager',
]);
$class = TestHelpers::createClass(
DynamicLocalTasks::class,
['plugin_id',
],
['config.factory']);
$this->assertInstanceOf(DynamicLocalTasks::class, $class);
}
/**
* Tests the initEntityTypeManagerInterface.
*/
public function testInitEntityTypeManagerStubs() {
TestHelpers::initEntityTypeManagerStubs();
$entityTypeManager = \Drupal::service('entity_type.manager');
$this->assertInstanceOf(EntityTypeManagerInterface::class, $entityTypeManager);
}
/**
* Tests the initService() method with a service that has a parent.
*/
public function testInitServiceWithParent() {
$logger = TestHelpers::service('logger.channel.default');
$moduleHandler = TestHelpers::service('module_handler');
$service = TestHelpers::initService('plugin.manager.block');
$this->assertSame($logger, TestHelpers::getPrivateProperty($service, 'logger'));
$this->assertSame($moduleHandler, TestHelpers::getPrivateProperty($service, 'moduleHandler'));
}
}
