5185

Symfony2 functional test and session persistance

Question:

Here is my problem, I add session variable from functional test controller and they don't popup on action targeted by test.

I made a login method and used <a href="http://symfony.com/doc/current/cookbook/testing/simulating_authentication.html" rel="nofollow">cookbook advice</a> to log in. I tuned it a bit to allow 2 accounts login : admin and superadmin

/** * @param $account string the account to log in with (authorized : superadmin and admin) */ protected function logIn($account) { $this->session = $this->container->get('session'); // Cookbook try // $this->session = new Session(new MockFileSessionStorage()); $user = $this->em->getRepository('LCHUserBundle:User')->findOneByUsername($account); $firewall = 'admin_area'; switch($account) { case self::SUPER_ADMIN_LOGIN: $token = new UsernamePasswordToken($user, $account, $firewall, array('ROLE_SUPER_ADMIN')); $this->client->setServerParameter("SERVER_NAME", SiteControllerTest::ROOT_SITE); $this->client->setServerParameter("HTTP_HOST", SiteControllerTest::ROOT_SITE); break; case self::ADMIN_LOGIN: $token = new UsernamePasswordToken($user, $account, $firewall, array('ROLE_ADMIN')); // Session var I wish to have on my controller action tested $this->session->set('currentSite', $this->em->getRepository('LCHMultisiteBundle:Site')->find(1)); $this->session->save(); // Use to force server canonical name for admin test $this->client->setServerParameter("SERVER_NAME", SiteControllerTest::ROOT_SITE); $this->client->setServerParameter("HTTP_HOST", SiteControllerTest::TEST_SITE); break; default: throw new UsernameNotFoundException('Username provided doesn\'t match any authorized account'); } // Save user in session $this->session->set('_security_'.$firewall, serialize($token)); $this->session->set('user', $user); $this->session->save(); // $this->container->set('session', $this->session); $cookie = new Cookie($this->session->getName(), $this->session->getId()); $this->client->getCookieJar()->set($cookie);

My setUp() method does this :

/** * {@inheritDoc} */ protected function setUp() { // Initiates client $this->client = static::createClient(); $this->container = $this->client->getContainer(); $this->application = new Application($this->client->getKernel()); $this->application->setAutoExit(false); $this->translator = $this->container->get('translator'); $this->em = $this->container ->get('doctrine') ->getManager(); }

You can see that I set session vars for authentication. They appear correctly when I dump session var from tested action, but if I add my currentSite session var, it seems not persisted. As I use the test container provided by client, it should be passed on shouldn't it?

PS : I also overrided Client class, according to <a href="https://stackoverflow.com/questions/38380193/symfony2-functional-test-client-force-server-param-server-name" rel="nofollow">this other question</a>.

I found numerous posts on topic but none provide any working solution (<a href="https://stackoverflow.com/questions/29133505/symfony2-functional-test-with-session-and-post" rel="nofollow">this one</a>, <a href="https://stackoverflow.com/questions/25994888/symfony2-functional-test-session-persistence" rel="nofollow">this one</a> or <a href="https://stackoverflow.com/questions/9621359/how-can-i-persist-data-with-symfony2s-session-service-during-a-functional-test" rel="nofollow">that one</a>). I also found this <a href="http://symfony.com/doc/current/components/http_foundation/session_testing.html" rel="nofollow">cookbook article</a>.

<strong>UPDATE :</strong> thanks to Alex Blex remark, I clarify here some parts of my question.

<ul><li>setUp() and logIn() are both parts of a custom WebTestCase class, embedding tools needed by my application specificities (such as translator...)</li> <li>My main point here is to set session params in test controller AND retrieve those session params in tested actions</li> </ul>

Answer1:

It is not quite clear what you are testing, what your expectations, and where it fails. It would make sense to add the actual test. Why do you need container, translator, etc in your tests at all?

There is nothing special needs to be done for sessions. Consider this example controller, which persists value of 'test' in session and increments it on consecutive calls:

/** * @Route("/session") * @Method({"GET"}) */ public function session() { $session = $this->container->get('session'); $current = $session->get('test', 0); $session->set('test', $current + 1); return new Response($current); }

And this test passes:

/** * @test */ public function session_increments() { $client = static::createClient(); $client->request("GET", '/session'); $this->assertEquals('0', $client->getResponse()->getContent()); $client->request("GET", '/session'); $this->assertEquals('1', $client->getResponse()->getContent()); }

Your application logic may be way more complex, but the test should remain pretty much the same - first call to login, second call to assert the response contains something unique to the logged-in user.

<strong>UPDATE</strong>

Playing with internal implementation in functional tests should be avoided as much as possible, yet, may be essential for some edge-cases, e.g. to simplify testing scenarios.

The following example tests the same controller by setting specific value to the session variable from within the test scenario, and check the value is returned by the app:

/** * @test */ public function session_returns_value() { $client = static::createClient(); $session = $client->getContainer()->get('session'); $session->set('test', 12); $client->request("GET", '/session'); $this->assertEquals('12', $client->getResponse()->getContent()); }

Recommend

  • How to retrieve data from an XML file in a Sharepoint 2010 Feature Event Receiver?
  • Python: Mapping between two arrays with an index array
  • Implementation of Thread-local storage (TLS) in C/C++ (multithreading)
  • how to compile code from svn into jar file?
  • ASP.NET, C# How to Pass a StringQuery to a custom SQL Command
  • Refresh other frame, from another frame. Jquery
  • Full 8 bit adder, illogical output
  • R h2o.glm - issue with max_active_predictors
  • IE6 changes DOCTYPE to a bad one
  • Doctrine/Symfony entity generator and generating entity from one table
  • C#: Import/Export Settings into/from a File
  • Default parameter as generic type
  • During installation of Django, why do I keep getting ImportError: No module named django?
  • pillow imaging ImportError
  • Ionic 2 storage is not cleaning up on uninstall - Only for signed APK
  • All Classes Conforming to Protocol Inherit Default Implementation
  • Resize panoramic image to fixed size
  • Finding past revisions of files in StarTeam w/ .NET SDK / C#
  • Obtain ObjectIdHex value from mgo query
  • Volusion's generic SQL folder, functionality
  • How to check if every primary key value is being referenced as foreign key in another table
  • ILMerge & Keep Assembly Name
  • Which linear programming package should I use for high numbers of constraints and “warm starts” [clo
  • Websockets service method fails during R startup
  • Why winpcap requires both .lib and .dll to run?
  • How to delete a row from a dynamic generate table using jquery?
  • Acquiring multiple attributes from .xml file in c#
  • using HTMLImports.whenReady not working in chrome
  • How to set the response of a form post action to a iframe source?
  • How do you join a server to an Active Directory (domain)?
  • coudnt use logback because of log4j
  • Change div Background jquery
  • Qt: Run a script BEFORE make
  • Authorize attributes not working in MVC 4
  • How can I remove ASP.NET Designer.cs files?
  • python draw pie shapes with colour filled
  • EntityFramework adding new object to nested object collection
  • Is there any way to bind data to data.frame by some index?
  • reshape alternating columns in less time and using less memory
  • How can i traverse a binary tree from right to left in java?