How to mock Symfony 2 service in a functional test?
Solution 1
After you create ServiceA
mock, you need to pass it to client's container (not the one from kernel's because client object builds its own kernel). Try this:
$client = self::createClient();
$serviceA = $this->getMockBuilder('ServiceA')
->disableOriginalConstructor()
->getMock();
$client->getContainer()->set('my_bundle.service.a', $serviceA);
Pay attention, that you must inject this mocked service every time you make a request. It's because the client rebuilds kernel between each two requests.
Solution 2
You should not mock your tested class, you should mock the Redis class and inject it.
If Redis isn't used for this test, you need not even configure the mock.
$redis = $this->getMockBuilder('Redis')->disableOriginalConstructor()->getMock();
$serviceA = new ServiceA($redis);
Solution 3
There is special tool which takes care of mocked services - https://github.com/ramunasd/symfony-container-mocks
It's easy like that:
$service = static::$kernel->getContainer()->prophesize('my.custom.service');
vishal
Updated on March 03, 2020Comments
-
vishal about 4 years
I have symfony service which uses redis connection in some methods but not in all methods.
class ServiceA { private $redis; public function __construct($redis) { $this->redis = $redis; } public function getRequest($param1, $param2) { $result = $param1+ $param2; return $request; } .. other methods which use $redis connection }
I am writing functional test for the code which use only getRequest method (this method does not need redis connection) but as the constructor takes the connection as an argument, when I run test it tried to connect redis server.
How can I write mock service which does not use redis connection at all and ignore original constructor.
I am trying approach mentioned below but no success. It still tries to connect redis eventhough I have disabled original constructor.
http://blog.lyrixx.info/2013/04/12/symfony2-how-to-mock-services-during-functional-tests.html
$serviceA = $this->getMockBuilder('ServiceA') ->disableOriginalConstructor() ->getMock(); static::$kernel->getContainer()->set('my_bundle.service.a', $serviceA);
-
magnetik almost 9 yearsEmphase on the "you need to pass it to the client's container (not the one from kernel)".
-
Rvanlaak almost 8 yearsDoes
$client->getContainer()->set('my_bundle.service.a', $serviceA)
imply that$container->get()
will not instantiate the service anymore? We want to "override" the service but still want the container to inject the service its dependencies afterwards. -
Cyprian almost 8 yearsNo, it won't instantiate the service anymore once you set the object by "set" method. You need to take care of it by yourself.