了解PHPUnit中的导入/使用

时间:2019-06-13 15:48:19

标签: php symfony phpunit

在PHPUnit测试中,我试图获取我的symfony应用程序中实现特定接口的所有类。我的应用程序代码位于App的命名空间中,而我的测试则位于Tests的命名空间中。

如果我实例化(或“使用”),此TestCase代码仅列出一个类(最上方的use语句无效)

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 :(得分:0)

由于使用的是KernelTestCase,因此您可以访问Container,在其中可以通过标记实现接口的所有服务并将它们通过以下方式传递给Registry Service来轻松实现它: 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();

您可以在此处找到有关如何使用服务标签的更多详细信息:

答案 1 :(得分:0)

我的解决方案类似于@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;
}