如何在 Symfony 中实例化自动装配服务?
How to instantiate autowired services in 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,自动装配设置为 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 Fatal error: Uncaught ArgumentCountError: Too few arguments to
function App\Test\OrderAbstractionTest::__construct(), 0 passed in
/var/www/html/autocom/bin/.phpunit/phpunit-6.5/src/Framework/TestSuite.php
on line 476 and exactly 1 expected in
/var/www/html/autocom/tests/OrderAbstractionTest.php:13
如果知道如何将诸如 OrderAbstraction 之类的服务实例化到其他服务、测试,那就太好了。因为大多数我在控制器中做这样的事情:
$order = new OrderAbstraction($this->em);
最终为我工作的是 php unit mock,我的代码现在如下所示:
public function testDays(){
$em = $this->getMockBuilder(EntityManager::class)
->disableOriginalConstructor()
->getMock();
$order = new OrderAbstraction($em);
$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);
}
如果自动装配设置为 true,则 services.yml 中不需要任何内容。在您的 OrderAbstraction.php 中将 EntityManager 替换为 EntityManagerInterface 以获取在您的服务自动装配时自动注入的 EntityManager 实例。
OrderAbstraction.php
use Doctrine\ORM\EntityManagerInterface;
class OrderAbstraction {
/**
* @var EntityManager
*/
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
...
}
}
编辑
由于这会在基本控制器中按预期工作,因此您不能使用单元测试的构造函数 class 来注入您的服务。根据 Symfony 的 blog :
In Symfony 4.1, tests allow fetching private services by default.
In practice, tests based on WebTestCase and KernelTestCase now access to a special container via the static::$container property that allows fetching non-removed private services:
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 的更多信息,请参阅
我想实例化 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,自动装配设置为 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 Fatal error: Uncaught ArgumentCountError: Too few arguments to function App\Test\OrderAbstractionTest::__construct(), 0 passed in /var/www/html/autocom/bin/.phpunit/phpunit-6.5/src/Framework/TestSuite.php on line 476 and exactly 1 expected in /var/www/html/autocom/tests/OrderAbstractionTest.php:13
如果知道如何将诸如 OrderAbstraction 之类的服务实例化到其他服务、测试,那就太好了。因为大多数我在控制器中做这样的事情:
$order = new OrderAbstraction($this->em);
最终为我工作的是 php unit mock,我的代码现在如下所示:
public function testDays(){
$em = $this->getMockBuilder(EntityManager::class)
->disableOriginalConstructor()
->getMock();
$order = new OrderAbstraction($em);
$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);
}
如果自动装配设置为 true,则 services.yml 中不需要任何内容。在您的 OrderAbstraction.php 中将 EntityManager 替换为 EntityManagerInterface 以获取在您的服务自动装配时自动注入的 EntityManager 实例。
OrderAbstraction.php
use Doctrine\ORM\EntityManagerInterface;
class OrderAbstraction {
/**
* @var EntityManager
*/
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
...
}
}
编辑
由于这会在基本控制器中按预期工作,因此您不能使用单元测试的构造函数 class 来注入您的服务。根据 Symfony 的 blog :
In Symfony 4.1, tests allow fetching private services by default. In practice, tests based on WebTestCase and KernelTestCase now access to a special container via the static::$container property that allows fetching non-removed private services:
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 的更多信息,请参阅