0

i have this code:

/**
 * Defines a wrapper target around a paragraph bundle's target field.
 *
 * @FeedsTarget(
 *   id = "feeds_para_mapper_temp_target",
 *   field_types = {
 *     "entity_reference_revisions",
 *   },
 *   arguments = {
 *     "@entity.manager",
 *     "@entity_field.manager"
 *   }
 * )
 */
class TempTarget extends FieldTargetBase implements, ConfigurableTargetInterface,
{
  protected $entity_type_manager;
  protected $field_manager;
  public function __construct(array $conf, $id, array $def, EntityTypeManagerInterface $en_man, EntityFieldManagerInterface $f_man)
  {
    parent::__construct($conf, $id, $def);
    $this->entity_type_manager = $en_man;
    $this->field_manager = $f_man;
  }
  // Here is where i need the instance, and it's weird because it gets called 
  // without instantiating this class:
  public function defaultConfiguration(){
    // This function create a form configuration and return it:
    $definition = $this->targetDefinition;
    $field = $definition->getFieldDefinition();
    $instance = $this->createTargetInstance($field,$this->feedType)
  }
  // Calls this plugin manager to get instance of another plugin
  public function createTargetInstance(FieldConfigInterface $field, FeedTypeInterface $feed_type){
    // This is where the test is failing:
    $manager = \Drupal::service('plugin.manager.feeds.target');
  }
}

what it does it calls a plugin manager in order to create instance definition, whenever it gets tested i see this error:

\Drupal::$container is not initialized yet.

which i know is caused by calling to the service i have tried this in the test file:

$container = new ContainerBuilder();
$manager = $this->prophesize('Drupal\feeds\Plugin\Type\FeedsPluginManager');
$container->set('plugin.manager.feeds.target', $manager);
\Drupal::setContainer($container);

Not working. i tried as the answer suggested in the comment bellow to add implement ContainerInjectionInterface not working, and with ContainerFactoryPluginInterface as this article suggested, not working too, in both implementations the create() method is never get called i tried to add this to he annotation:

 *   arguments = {
 *     "@entity.manager",
 *     "@entity_field.manager",
 *     "@plugin.manager.feeds.target"
 *   }

with this constructor:

public function __construct(array $$conf, $id, array $def, EntityTypeManagerInterface $en_m, EntityFieldManagerInterface $f_m, FeedsPluginManager $p_m)
  {
    $stop = null;
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entity_type_manager = $en_m;
    $this->field_manager = $f_m;
    $this->plugin_manager = $p_m;
  }

and it's working only if this class is instantiated, and as i said it's not when the defaultCongiguration() get called, i can go without the plugin manager at this stage but i really prefer if i can have it in this function.

Update:

The reason why implementing either ContainerInjectionInterface or ContainerFactoryPluginInterface didn't work is because i added my dependencies in the arguments, annotation and in the create() method too.

closed as off-topic by kiamlaluno Jul 12 at 12:28

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This question was caused by a problem that can no longer be reproduced, was solved by a cache clear, or was a simple typographical error. While similar questions may be on-topic here, this one was resolved in a manner unlikely to help future readers." – kiamlaluno
If this question can be reworded to fit the rules in the help center, please edit the question.

  • I don't see the entire class but shouldn't that be passed in instead of called statically? – Kevin Nov 18 '18 at 17:11
  • no the test is failing with this exception Drupal\Core\DependencyInjection\ContainerNotInitializedException: i think a plugin manager is some kind of service: drupal.org/docs/8/api/plugin-api/… – Hussein Nov 18 '18 at 17:15
  • 1
  • I was confused why this was a duplicate at first, but to explain, I think that leymannx is suggesting you can work around your question by by injecting FeedsPluginManager into the static method. Then it can be mocked without creating a container. I see how this could be a duplicate given that. – mradcliffe Nov 19 '18 at 3:06
  • it is not duplicate, and i already tried it and not working there is something worked for me but only if the constructor got called, but wait you said injecting into static method, is there such thing ?? – Hussein Nov 19 '18 at 7:41
1

This is probably a unit test (not mentioned in the OP). If so, the intention should be to test the methods of the TempTarget class, which means, that the first thing needed would be to instantiate an instance of that class, e.g.

/**
 * Instantiates and returns a TempTarget object.
 */
protected function getTempTargetInstance()
{
  $id = $this->generateId();
  $def = $this->generateDef();
  // This is where you mock the constructor dependencies/services.
  // You probably will need to create a mock like this:
  //   $this->getMockBuilder('Drupal\Core\Entity\EntityTypeManager')
  //     ->disableOriginalConstructor()
  //     ->getMock();
  $this->entityTypeManager = $this->getEntityTypeManagerMock();
  $this->entityFieldManager = $this->getEntityFieldManagerMock();

  // You can now call the constructor.
  $tempTarget = new TempTarget($id, $def, $this->entityTypeManager, $this->entityFieldManager);
  return $tempTarget;
}

At this point, your object should be instantiated and you can call methods on it to assert the assumptions you want to be testing. For example:

public function testDefaultConfigurationMethod()
{
  $tempTarget = $this->getTempTargetInstance();
  $formConfiguration = $tempTarget->defaultConfiguration();
  // Test different assertions given the $formConfiguration object.  
}

However, at the time you call defaultConfiguration() you know that you need a container available that holds an entry for plugin.manager.feeds.target, so, you have to have that prepared in advance. The right place for that would be your setUp() method in your class, for example:

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

  // Provide a mock service container, for the services our module uses.
  $container = new ContainerBuilder();
  $container->set('plugin.manager.feeds.target', $this->getFeedsTargetPluginManagerMock());
  \Drupal::setContainer($container);
  ...
  // Further setting-up of your testing class.
}

with getFeedsTargetPluginManagerMock() looking something like this:

/**
 * Creates and returns a mock for the feeds  
 */
protected function getFeedsTargetPluginManagerMock() {
  $feedsTargetPluginManager = $this
    ->getMockBuilder('Drupal\feeds\Plugin\Type\FeedsPluginManager')
    ->disableOriginalConstructor()
    ->getMock();
  ...
  // Further mocking of the objects methods if needed.
  ...
  return $feedsTargetPluginManager;
}

Good luck!

  • Sure thing, did you manage to make it work in the end? – Stefanos Petrakis Nov 21 '18 at 19:07
  • Yes the test is working now, i had to change few things in the main code – Hussein Nov 21 '18 at 19:10
  • Good to know, would be very helpful for others landing here if you could update your question with the final details. – Stefanos Petrakis Nov 21 '18 at 20:05

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