首页 > 解决方案 > 如何在 Symfony 中实例化自动装配服务?

问题描述

我想在测试用例的构造函数中实例化需要实体管理器的 OrderAbstraction 服务。

class OrderAbstraction
{
    ...

    /**
     * @var EntityManager
     */
    private $em;

public function __construct(EntityManager $em)
    {
        $this->em = $em;
        ...
    }
}

我尝试自动装配 OrderAbstractionTest 并将 OrderAbstraction 和实体管理器作为参数。

class OrderAbstractionTest extends TestCase
{
// tried with constructor and without it
    public function testDays(){
        $order = new OrderAbstraction();
        $order->dateFrom(new \DateTime('2019-08-20 14:00'));
        $order->dateTo(new \DateTime('2019-08-28 14:00'));

        $days = $order->days();
        $this->assertEquals(8, $days);
    }
}

我的 service.yaml,autowire 设置为 true

    App\Service\OrderAbstraction\:
        resource: '../src/Service/OrderAbstraction.php'
        arguments: 
            $em: '@Doctrine\ORM\EntityManager'

    App\Test\OrderAbstraction\:
        resource: '../tests/OrderAbstractionTest.php'
        arguments: 
            $em : '@Doctrine\ORM\EntityManager'

我不断得到这样的东西:

PHP 致命错误:未捕获的 ArgumentCountError:函数 App\Test\OrderAbstractionTest::__construct() 的参数太少,在 /var/www/html/autocom/bin/.phpunit/phpunit-6.5/src/Framework/TestSuite 中传递了 0。第 476 行的 php 和 /var/www/html/autocom/tests/OrderAbstractionTest.php:13 中预期的恰好 1

很高兴知道如何将诸如 OrderAbstraction 之类的服务实例化为其他服务、测试。因为大多数我在控制器中做这样的事情:

$order = new OrderAbstraction($this->em);

标签: symfonytestingsymfony4

解决方案


如果 autowire 设置为 true,您不需要 services.yml 中的任何内容。将 EntityManager 替换为OrderAbstraction.php中的 EntityManagerInterface 以在自动装配服务时自动注入 EntityManager 的实例。

OrderAbstraction.php

use Doctrine\ORM\EntityManagerInterface;

class OrderAbstraction {

  /**
   * @var EntityManager
   */
  private $em;

  public function __construct(EntityManagerInterface $em)
  {
    $this->em = $em;
    ...
  }
}

编辑

由于这将在基本控制器中按预期工作,因此您不能使用单元测试类的构造函数来注入您的服务。根据 Symfony 的博客

在 Symfony 4.1 中,测试默​​认允许获取私有服务。在实践中,基于 WebTestCase 和 KernelTestCase 的测试现在通过 static::$container 属性访问一个特殊的容器,该属性允许获取未删除的私有服务:

OrderAbstractionTest.php

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use App\Service\OrderAbstraction;

class OrderAbstractionTest extends WebTestCase {

  /**
   * @var OrderAbstraction
   */
  private $order;

  public function testDays() {
    self::bootKernel();
    $this->order = static::$container->get(OrderAbstraction::class);

    $this->order->dateFrom(new \DateTime('2019-08-20 14:00'));
    $this->order->dateTo(new \DateTime('2019-08-28 14:00'));

    $days = $this->order->days();
  }
}

在 Symfony 4.3 上测试并正常工作有关 Symfony 3.4 和 4.0 的更多信息,
请参阅此 anwser


推荐阅读