Symfony2 request and session meaning in PHPUnit

I have a class that requires the Symfony2 @request_stack service, which returns an instance of Symfony\Component\HttpFoundation\RequestStack . I use it to get the POST and GET values.

And also my class uses Symfony\Component\HttpFoundation\Session from Request->getSession() , which it calls to get the current session.

My class now has a method that looks something like this:

 class MyClass { public function doSomething() { //Get request from request stack. $Request = $this->RequestStack->getCurrentRequest(); //Get a variable from request $var = $Request->request->get('something'); //Processes $var into $someprocessedvar and lets say it equal to 3. //Set value to session. $this->Request->getSession()->set('somevar', $someprocessedvar); } } 

I need to be able to:

  • Mock RequestStack .
  • Get Request from RequestStack
  • Get Session from Reques t;

With all that said, how can I verify that MyClass successfully sets the expected value in a session?

+7
symfony service mocking phpunit
source share
5 answers

According to this: http://api.symfony.com/2.4/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.html

I need to work something like this:

 public function testCompanySession() { $Request = new Request(); $Request->setSession( new Session(new MockArraySessionStorage()) ); $CompanySessionMapper = new CompanyMapper($Request); $Company = new Company(); $Company->setName('test'); $CompanySessionMapper->set($Company); $Company = new Company(); $CompanySessionMapper->get($Company); $this->assertEquals($Company->getName(), 'test'); } 

There is only one test for the type of an object in my case, since I only verify the correctness of the session name and the correct receipt / storage of the object in the session. CompanyMapper class uses a session to store a company object among other session / application related functions.

0
source share

Not all code is worth unit testing. This is usually an indication that your code can be simplified. When you are unit test code, which is somewhat complex, tests can become a burden, and as a general rule, it would be better to integrate the test from edge to edge in these cases. It is also unclear in your example how your class receives RequestStack , so I assume it was introduced in __construct .

With that said here, how you will test this code:

 protected function setUp() { $this->requestStack = $this->getMock('Fully-qualified RequestStack namespace'); $this->SUT = new MyClass($this->requestStack); } /** @test */ public function it_should_store_value_in_the_session() { $value = 'test value'; $request = $this->getMock('Request'); $request->request = $this->getMock('ParameterBag'); $session = $this->getMock('Session'); $this->requestStack ->expects($this->atLeastOnce()) ->method('getCurrentRequest') ->will($this->returnValue()); $request->request ->expects($this->atLeastOnce()) ->method('get') ->with('something') ->will($this->returnValue($value)); $request ->expects($this->once()) ->method('getSession') ->will($this->returnValue($session)); $session ->expects($this->once()) ->method('set') ->with('somevar', $value); $this->SUT->doSomething(); } 

This should give you a starting point, but be careful that you have bullying in your tests, because very small changes in the implementation details may cause your tests to fail, even if the behavior is still correct, and this is something you want to avoid as much as it is possible that the tests are not worth supporting.

Edit: I thought a little about your question and realized that you can usually introduce a session as a dependency. If possible in your use case, this will simplify the tests.

+7
source share

You do not need to make fun of RequestStack , it is a super simple class. You can simply create a fake request and click on it. You can also make fun of the session.

 // you can overwrite any value you want through the constructor if you need more control $fakeRequest = Request::create('/', 'GET'); $fakeRequest->setSession(new Session(new MockArraySessionStorage())); $requestStack = new RequestStack(); $requestStack->push($fakeRequest); // then pass the requestStack to your service under test. 

But from a testing point of view, having to bother with the internal elements of a class is not a good sign. Perhaps you can create a handler class to encapsulate the desired logic from the query stack so that you can test more easily.

+2
source share

It is difficult to imagine a situation when you have to deal with the GET / POST parameters inside the device under test. Ask the dispatcher to process HTTP requests and sessions (which is pretty much what they are there), and pass the variables to the appropriate classes to handle the rest.

As they say, Kevin’s answer is a possible solution if you want to go down this route.

+1
source share

Anyone who comes from Google, like me, wants to know how to mock the content of the request is as simple:

 use AppBundle\Controller\DefaultController; use Symfony\Component\HttpFoundation\Request; use PHPUnit\Framework\TestCase; class DefaultControllerTest extends TestCase { //@dataProvider? public function testWithMockedRequest() { //create a request mock $request = $this ->getMockBuilder(Request::class) ->getMock(); //set the return value $request ->expects($this->once()) ->method('getContent') ->will($this->returnValue('put your request data here')); //create your controller $controller = new DefaultController(); //get the Response based on your Request $response = $controller->myRequestAction($request); //assert! $this->assertEquals(200, $response->getStatusCode()); } } 

As you can see, you can execute a real controller that uses $request->getContent()

I hope this helps someone.

0
source share

All Articles