Unit #test for your #Controller with #PhpUnit and #Symfony.. With a little use case of #DepedenceInjaction test https://t.co/JNb39EyRly #php
— Gianluca Arbezzano (@GianArb) May 21, 2015
In this article I would like share with you a little experience with:
- Symfony MVC
- PhpUnit
- Symfony Dependence Injaction
This is an example of very easy controller.
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class SomeStuffController extends FOSRestController
{
/**
* @Rest\Post("/go")
* @return array
*/
public function goAction(Request $request)
{
if($this->container->getParameter("do_stuff")) {
$body = $this->container->get("stuff.service")->splash($request->getContent());
}
return [];
}
}
$this->container->getParameter("do_stuff")
is a boolean parameter that enable or disable a feature, How can I test this snippet?
I can try to write a functional test but in my opinion is easier write a series of unit tests with PhpUnit to validate my expectations.
Expectations
- If
do_stuff
parameter is false function get by my container will be call zero times - If
do_stuff
parameter is true function get by my container will be call one times
<?php
namespace AppBundle\Tests\Controller;
use Liip\FunctionalTestBundle\Test\WebTestCase;
use AppBundle\Controller\SomeStuffController;
class SomeStuffControllerTest extends WebTestCase
{
public function testDoStuffIsTrue()
{
$request = $this->getMock("Symfony\Component\HttpFoundation\Request");
$container = $this->getMock("Symfony\Component\DependencyInjection\ContainerInterface");
$service = $this->getMockBuilder("Some\Stuff")->disableOriginalConstructor()->getMock();
$container->expects($this->once())
->method("getParameter")
->with($this->equalTo('do_stuff'))
->will($this->returnValue(true));
$container->expects($this->once())
->method("get")
->with($this->equalTo('stuff.service'))
->will($this->returnValue($service));
$controller = new SameStuffController();
$controller->setContainer($container);
$controller->goAction($request);
}
}
This is my first expetection “If do_stuff
param is true I call stuff.service
”.
In this controller I use a few objects, Http\Request, Container and stuff.service
in this example is a Some\Stuff
class.
In the first step I have created one mock for each object.
<?php
$request = $this->getMock("Symfony\Component\HttpFoundation\Request");
$container = $this->getMock("Symfony\Component\DependencyInjection\ContainerInterface");
$service = $this->getMockBuilder("Some\Stuff")->disableOriginalConstructor()->getMock();
In the second step I have written my first expetctation, “Call only one time function getParameter
from $container
with argument do_stuff and it returns true”.
<?php
$container->expects($this->once())
->method("getParameter")
->with($this->equalTo('do_stuff'))
->will($this->returnValue(true));
Thanks at this definitions I know that there will be another effect, my action will call only one time $container->get("stuff.service")
and it will be return an Some\Stuff object.
The second test that we can write is “if do_stuff
is false $contaner->get("stuff.service")
it will not be called.
<?php
public function testDoStuffIsFalse()
{
$request = $this->getMock("Symfony\Component\HttpFoundation\Request");
$container = $this->getMock("Symfony\Component\DependencyInjection\ContainerInterface");
$service = $this->getMockBuilder("Some\Stuff")->disableOriginalConstructor()->getMock();
$container->expects($this->once())
->method("getParameter")
->with($this->equalTo('do_stuff'))
->will($this->returnValue(false));
$container->expects($this->never())
->method("get")
->with($this->equalTo('stuff.service'))
->will($this->returnValue($service));
$controller = new SameStuffController();
$controller->setContainer($container);
$controller->goAction($request);
}