Понимание импорта / использования в PHPUnit - PullRequest
0 голосов
/ 13 июня 2019

В тесте PHPUnit я пытаюсь получить все классы моего приложения Symfony, которые реализуют определенный интерфейс.Мой код приложения находится в пространстве имен App, мои тесты - в Tests.

. Этот код TestCase содержит только класс , если я его создаю (или "использую") it (*)1007 * операторов сверху не действуют):

namespace Tests\ReportPlaceholder;

use App\ReportPlaceholder\LimitModificationsPlaceholder;
use App\ReportPlaceholder\SimpleEvaluatePlaceholder;
use App\ReportPlaceholder\ReportPlaceholderInterface;

class MyTest extends KernelTestCase{


    public function provider(){

        new SimpleEvaluatePlaceholder(); // <-- if I comment this line, the class is *not* found
        // also a usage of SimpleEvaluatePlaceholder::class suffices

        return array_map(function($p) { return [$p]; }, 
                array_filter(get_declared_classes(), function($className){
                     return in_array(ReportPlaceholderInterface::class, class_implements($className));}
        ));
    }
}

provider возвращает только в этом сценарии SimpleEvaluatePlaceholder

Мой composer.json равен

"autoload": {
    "psr-4": {
        "App\\": "src/"
    }
},
"autoload-dev": {
    "psr-4": {
        "Tests\\": "tests/"
    }
},

и phpunit.xml читает:

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.5/phpunit.xsd"
     backupGlobals="false"
     colors="true"
     bootstrap="config/bootstrap.php"
     verbose="true"
     debug="false"
     stopOnFailure="true">

Ответы [ 2 ]

0 голосов
/ 17 июня 2019

Мое решение похоже на то, что предполагал @peetya: мне нужно загрузить дополнительное ядро ​​в provider, чтобы получить список сервисов (и сразу после этого закрыть его снова):

public function provider()
{
    $ret = [];
    self::bootKernel();
    foreach (static::$container->get('report_helper')->placeholders as $placeholder){
        /** @var $placeholder ReportPlaceholderInterface */
        $ret[] = [get_class($placeholder)];
    }
    static::ensureKernelShutdown();
    return $ret;
}
0 голосов
/ 13 июня 2019

Поскольку вы используете KernelTestCase, у вас есть доступ к контейнеру, где вы можете легко добиться этого, пометив все ваши службы, которые реализуют ваш интерфейс, и передав их в службу реестра следующим образом (Symfony 3.4 или выше) :

# services.yml
services:
  _instanceof:
    YourInterface:
      tags: ['my_custom_tag']

  App\Registry\MyCustomTagRegistry:
    arguments: [!tagged my_custom_tag]

Ваш класс реестра:

class MyCustomTagRegistry
{
  /** @var Traversable */
  private $services;

  public function __construct(iterable $services = [])
  {
    $this->services = $services;
  }

  public function getServices(): array
  {
    return (array) $this->services;
  }
}

Тогда в вашем тесте вам нужно получить данный сервис из контейнера:

$services = self::$container->get(MyCustomTagRegistry::class)->getServices();

Подробнее о работе с тегами сервиса вы можете узнать здесь:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...