symfony: [Session][Test] Cannot set session ID after the session has started.
Hi there,
the exception is thrown by this line: https://github.com/symfony/symfony/blob/2.5/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php#L134
My setup works completely fine within a valid PHP environment (without TestSessionListener) - data getting stored in the session before the TestSessionListener::onKernelRequest has been executed (using MockFileSessionStorage).
What’s the intention of this exception? I can’t get my head around it. The TestSessionListener is explicitly doing this (setId) and if there is another object accessing the session before the TestSessionListener sets the id, an id is automatically generated. The listener is not correctly mimicking the session creation of PHP and this exception makes it (for some parts) unusable.
If there is no actual use on this exception, it may be removed, no?
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 1
- Comments: 49 (33 by maintainers)
Commits related to this issue
- provide setup for symfony/symfony#13450 — committed to havvg/symfony-standard by havvg 9 years ago
- symfony/symfony#13450 means tests currently broken. Hacked around it by swapping out test session class. Also updated PHP deps — committed to camdram/camdram by hoyes 9 years ago
- bug #28433 [HttpFoundation] Allow reuse of Session between requests if ID did not change (tgalopin) This PR was merged into the 2.8 branch. Discussion ---------- [HttpFoundation] Allow reuse of Ses... — committed to symfony/symfony by nicolas-grekas 6 years ago
- bug #28433 [HttpFoundation] Allow reuse of Session between requests if ID did not change (tgalopin) This PR was merged into the 2.8 branch. Discussion ---------- [HttpFoundation] Allow reuse of Ses... — committed to symfony/http-foundation by nicolas-grekas 6 years ago
I had randomly the same problem in Symfony 3.2.* during functional tests. Solution presented by @rgarcia-martin didn’t work for me, so I made own with following code:
and in config_test.yml :
Seems it works.
Hi everybody!
This work for me: Im doing functionality tests in my Symfony 2.6 app. That test go against routes protected and i need to do the requests with an UsernamePasswordToken setted at the session.
-The cookie always have the same id that the session, but that Exception is thrown when the cookie is setted and TestSessionListener check that the cookie have an item with the session name.
My solution:
config_test.yml:Why it have to set the id again and expose us to get an exception if the session is started?
I hope help you! Bye!
Hoping this will help someone. I’m using the Liip Functional Test Bundle and was getting this issue. The way I solved it was to save the session before a request was made.
Example:
config_test.yml
Symfony Version: 3.4.2 Liip Functional Test Version: 1.9.0
Hope this helps
One of my coworkers solved this problem. The config_test.yml had these lines:
Deleting
test: ~from config_test.yml got rid of the error.If you interested, I have worked around this by clearing the session between requests. In one test:
This means I didn’t have to apply fixes inside the Symfony code.
I’ve also encountered this issue in functional test extending WebTestCase. It was working fine before i disabled kernel rebooting (by calling disableReboot on test.client.class because of DB isolation - i want to share the same connection so it can run in one transaction).
There is a TestSessionListener class which sets session ID if present in cookies on every master request. Problem is when the session is shared between requests (which is also caused by disabling the kernel reboot). Then it tries to set the session id on already started session in MockArraySessionStorage.php:142
In this case this call is redundant since the same session ID is already present in the session.
I temporarily fixed it by extending MockArraySessionStorage (or MockFileSessionStorage) like this.
It is simpler than extending the TestSessionListener class. But if I understand it correctly then the listener is the place where the condition should be present.
Should it be fixed? Should i provide a PR? Have someone already provided a failing test case?
I stumbled upon this problem and may have a fix with https://github.com/symfony/symfony/pull/28433. Don’t hesitate to try and give your opinion on the PR or here. Thanks!
I ran into the same problem and found that the issue is that I have an event subscriber with a higher priority than Symfony’s
TestSessionListenerthat interacts with the session.So what happens is first my listener (priority 2048) calls
hason the session, but the session hasn’t started yet, so it is started with a random ID generated byMockArraySessionStorage.After that the
TestSessionListener(priority 192) is called and wants to set the ID of the session it retrieved from a session cookie, but this fails because a session was already started by my call tohasin my own listener, and you get the exceptionCannot set session ID after the session has started.I’ve “solved” this for now with a CompilerPass that removes the default tags from
TestSessionListenerand replaces it with tags with a higher priority forkernel.requestthan my own listener, so theTestSessionListeneris called before my own listener, and that solves the problem for me.Without resorting to gigantic numbers for the priority of
TestSessionListenerI’m not really sure how to structurally solve this problem though. And even with a very high priority there is always someone that needs an even higher priority for one reason or another and breaks it again.Maybe there is a way to retrieve all events subscribed to
kernel.request, finds the highest priority, and registerTestSessionListenerwith that highest priority + 1 in a CompilerPass somewhere? Rather nasty but would work.Or maybe we could pass the
RequestStackto theMockFileSessionStorageand let it use the cookie in the master request (if it exists) instead of generating it’s own ID. That would couple the two, but they are already coupled at the moment through theTestSessionListener. That would require the RequestStack have a master request upon first call though, and I’m not sure that something we can and/or should guarantee.Got the same issue with Liip Functional Test Bundle too, and Symfony 4.0.
Workaround for my case, inspired from https://github.com/symfony/symfony/issues/13450#issuecomment-147447252:
Then on the
Kernelclass:Work for me. But I’m sure the exception is not here for nothing. 😃
What is the state of this issue?
In my case I was using the @session service in the Twig Extension constructor, like:
The solution was just to store @session and use it later:
Thanks, anyway.
I fixed this during a 2.5 -> 2.6 upgrade by finding all references to
sessionin my source and removing them one-by-one til I found the culprit (as usual, the very last one.) It seems that passing the session to a service is OK, but accessing its variables or modifying it in the service’s constructor is a no-no unless the session is started. You can check this by checkingif($session->isStarted()).