I'm not entirely sure I understand your question but are you just asking how you log in programatically?
In my tests I simply do a call like:
$this->container->get('security.context')->setToken(
new UsernamePasswordToken(
'maintenance', null, 'main', array('ROLE_FIXTURE_LOADER')
)
);
In this instance 'maintenance' is not even a real User entity, its just a username that I made up for my fixtures so that they can access a service by having ROLE_FIXTURE_LOADER
but if you did want to login as a full user entity (so that they have the correct ACL ID) you can get a $user
object from the database and call:
$this->container->get('security.context')->setToken(
new UsernamePasswordToken(
$user, null, 'main', $user->getRoles())
)
);
This doesn't do a full login but it does work with RBAC and I don't see why it wouldn't work with ACL if you pass an actual user object.
As for functional testing of my front end if I need to login I just navigate to the login page and submit the form as per the testing docs. For either of those to work you do need access to the container so you need to extend WebTestCase
or roll your own ability to boot the kernel (see here).
I've a feeling I've mis-understood the question though (i.e. you need to do something more complex than just placing the token). Perhaps you could try to clarify a bit more what you mean by
passing or faking a login
A concrete example to plant a security token in a test:
First we make a base class for our tests to use which contain a login convenience method. This can be done by extending WebTestCase
and using the getContainer
method on a client
OR you can pull WebTestCase
apart to roll your own base class which just boots the kernel without a client and returns the container (see my link for two solutions to achieve that).
namespace Acme\SomeBundle\Tests;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
abstract class AcmeTestCase extends WebTestCase {
protected function loginAs($client, $username) {
$container = $client->getContainer();
$doctrine = $container->get('doctrine');
$user = $this->loadUser($doctrine, $username);
// First Parameter is the actual user object.
// Change 'main' to whatever your firewall is called in security.yml
$container->get('security.context')->setToken(
new UsernamePasswordToken(
$user, null, 'main', $user->getRoles()
)
);
}
private function loadUser($doctrine, $username) {
// Don't have to use doctrine if you don't want to, you could use
// a service to load your user since you have access to the
// container.
// Assumes User entity implements UserInterface
return $doctrine
->getRepository('AcmeUserBundle:User')
->findOneByUsername($username);
}
}
Then you just need to use your base class in any test you wish. Like so:
namespace Acme\SomeBundle\Tests\Entity;
use Acme\SomeBundle\Tests\AcmeTestCase;
class SomeEntityTest extends AcmeTestCase {
public function somethingTest() {
$this->loginAs(static::createClient(), 'SomeUsernameInDB');
// Do the rest of your test here.
}
}
Hopefully this helps.