Reputation: 115
I want to instantiate OrderAbstraction service which requires entity manager in constructor in a test case.
class OrderAbstraction
{
...
/**
* @var EntityManager
*/
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
...
}
}
I've tried to autowire OrderAbstractionTest and give a OrderAbstraction and entity manager as parameter.
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);
}
}
my service.yaml, autowire set to 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'
I keep getting something like this:
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
Would be great to know how to instantiate services like OrderAbstraction to other services, tests. Because most of the I do something like this in controllers:
$order = new OrderAbstraction($this->em);
Upvotes: 0
Views: 2879
Reputation: 1778
You don't need anything in the services.yml if autowire is set to true. Replace EntityManager by EntityManagerInterface in your OrderAbstraction.php to get an instance of EntityManager being automatically injected when your service is autowired.
OrderAbstraction.php
use Doctrine\ORM\EntityManagerInterface;
class OrderAbstraction {
/**
* @var EntityManager
*/
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
...
}
}
EDIT
As this would work as expected in a basic controller, you can't use the constructor of your unit test class to inject your service. According to Symfony's 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();
}
}
Tested and working fine on Symfony 4.3
See this anwser for more info about Symfony 3.4 and 4.0
Upvotes: 3
Reputation: 115
What end up working for me is php unit mock, my code now looks like this:
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);
}
Upvotes: 0