I'm currently creating my unit test for my application but it's the first time I do it.
I want to test this function :
/**
* This method search if the user is already in a team for the same tournament than the one passed in argument
* @param User $user
* @param Team $team
* @return bool|Team|mixed
*/
public function isAlreadyApplicant($user, Team $team) {
if (!$user || !$this->authorizationChecker->isGranted("ROLE_USER")) {
return false;
}
foreach ($user->getApplications() as $userTeam) {
/** @var Team $userTeam */
if ($userTeam->getTournament()->getId() === $team->getTournament()->getId()) {
return $userTeam;
}
}
foreach ($user->getTeams() as $userTeam) {
/** @var Team $userTeam */
if ($userTeam->getTournament()->getId() === $team->getTournament()->getId()) {
return $userTeam;
}
}
foreach ($user->getManagedTeam() as $userTeam) {
/** @var Team $userTeam */
if ($userTeam->getTournament()->getId() === $team->getTournament()->getId()) {
return $userTeam;
}
}
return false;
}
As you can see, the first test is to check if the user have the ROLE_USER.
When I try to "log my user", I have this message :
Fatal error: Call to a member function getToken() on null in \vendor\symfony\symfony\src\Symfony\Component\Security\Core\Authorization\AuthorizationChecker.php on line 56
I tried what I found in the Symfony doc but I must miss something. This is my test Class:
class ApplicationCheckerTest extends WebTestCase
{
protected $client = null;
public function setUp() {
$this->client = static::createClient();
/** @var User $user */
$user = $this->client->getContainer()->get('doctrine')->getManager()->getRepository('MGDUserBundle:User')->findOneBy(array("email" => '[email protected]'));
$this->loginUser("main", $user);
}
protected function loginUser($firewallName, UserInterface $user, array $options = array(), array $server = array())
{
$this->client = static::createClient();
$token = new UsernamePasswordToken($user, null, $firewallName, $user->getRoles());
static::$kernel->getContainer()->get('security.token_storage')->setToken($token);
$session = $this->client->getContainer()->get('session');
$session->set('_security_'.$firewallName, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
public function testIsAlreadyApplicantIsNotConnected()
{
$user = new User();
$team = new Team();
$router = $this->createMock(Router::class);
$authorizationChecker = $this->createMock(AuthorizationChecker::class);
$applicationChecker = new ApplicationChecker($router, $authorizationChecker);
$applicationChecker->isAlreadyApplicant($user, $team);
}
}
And my security.yml looks like :
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
provider: main
form_login:
login_path: fos_user_security_login
check_path: fos_user_security_check
logout:
path: fos_user_security_logout
target: /
remember_me:
secret: '%secret%'
I try to connect a user I created with fixtures.
I'm not sure about the way I try to do it, maybe I'm on the wrong path, don't hesitate to correct me if I'm wrong!
For information, I'm in Symfony 3.2.13
Have a good day
The WebTestCase
and the example from the Symfony documentation that you're using should be used for a functional test of your controller.
The way you have set up your authentication for the client is correct. But you are not using that client to make a request to the bootstrapped Symfony kernel in your test case. You are just making a simple unit test on a manually created instance of your service, which is fine.
You can simply use the PHPUnit\Framework\TestCase
for that.
It is possible to use the WebTestCase
to test your service and overwrite the TokenStorage
which is used in the AuthorizationChecker
in the kernel container instead of the client container, and then also fetch your service from the kernel container instead of instantiating it yourself. But I don't see much benefit in it. There is no need to test the Symfony component (if isGranted is working). That is in the scope of the Symfony project and most likely already covered there.
The reason for your error is, that a final method can't be mocked. As a workaround you can set the dependency in your ApplicationChecker
constructor to AuthorizationCheckerInterface
and then create a mock from the interface in your test.
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
$authorizationChecker->method('isGranted')->willReturn(true);