Sorry my question is very long.
How to mock entityManager in a service test extending KernelTestCase ?
Now, the explanation and my tests...
I am using Symfony3.2. My Application is standard. I have some Controller and I use WebTestCase to test them.
Generaly, my Controller verify parameters, call a service/a manager, handle some variables and push them to view and my test are pretty simple in test extending WebTestCase.
/**
* Test New Game Action
*/
public function testFooAction(){
//We mock the Service
$fooService = $this
->getMockBuilder(GameService::class)
->disableOriginalConstructor()
->getMock();
$fooService->expects(self::once())
->method('barMethod')
->willReturn($result);
//We create the client
$client = static::createClient();
$container = $client->getContainer();
//I put my mock here
$container->set('app.game-service', $fooService);
//I launch the request
$client->request('GET', '/foo');
//I handle the response
$response = $client->getResponse();
//I do some tests like this one
self::assertEquals(200, $response->getStatusCode());
}
As you can see, I do not call EntityManger, because I use Services and these lines to put my Services's Mock
//We create the client
$client = static::createClient();
$container = $client->getContainer();
//I put my mock here
$container->set('app.game-service', $fooService);
I have a problem to mock Entity Manager in my services. My Controller is tested but not My Service.
Here is the constructor initialized a simple protected property entityManager. The problem is this protected as you will see further...
/**
* FooService constructor.
* @param EntityManager $entityManager
*/
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
To Test my Service, here is my initial code :
<?php
class FooServiceTest extends KernelTestCase
{
/**
* Foo Service.
*
* @var FooService
*/
private $fooService;
/**
* Prepares the environment before running each test.
*/
protected function setUp()
{
parent::setUp();
self::bootKernel();
$this->fooService = static::$kernel->getContainer()
->get('app.foo-service') //HERE IS HOW I HANDLE MY SERVICE TO TEST IT
;
}
testStart Works perfectly, there is some database interaction.
I know that I can rollback data during test. But I want to Mock entityManager to verify the call of commit
method.
I try this to mock entity manager in my setUp :
protected function setUp()
{
parent::setUp();
$entityManager = $this
->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
$entityManager
->expects(once()) // I WANT EXACTLY ONE CALL TO COMMIT METHOD
->method('commit')
->willReturn(null);
self::bootKernel();
$container = static::$kernel->getContainer();
$container->set('doctrine.orm.entity_manager', $entityManager); // THIS LINE DOES NOTHING <=======
$this->gameService = static::$kernel->getContainer()
->get('app.game-service')
;
Thes code doesn't work. Mock is not in place. I still have the true entityManager. I think it is because the container is already closed. Do it is nut usefull to set
Like a Barbarian, I change the entityManager property to public
And I do that :
protected function setUp()
{
parent::setUp();
$entityManagerMock = $this
->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
$entityManagerMock
->expects(once()) // I WANT EXACTLY ONE CALL TO commit METHOD
->method('commit')
->willReturn(null);
self::bootKernel();
$this->gameService = static::$kernel->getContainer()
->get('app.game-service')
;
$this->gameService->entityManager = entityManagerMock;
It works perfectly. Test can be run. But it is NOT a good practice to have an entityManager in a public property
My question is : How to mock entityManager in a service test ?
(Sorry, I am not fluent in english)