A colleage changed the code of my service to use the isGranted method of of the AuthorizationCheckerInterface to check the rights. Like this:
$this->authorizationChecker->isGranted(Roles::ROLE_PERSON_VIEW);
Regretfully, he didn't adapt my phpunit tests so I am left with changing my tests so they pass again.
The service I am testing is created like this in my test:
protected function getService(string $id): ?object
{
$kernel = static::createKernel();
$kernel->boot();
return $kernel
->getContainer()
->get($id);
}
/** @var AuthorizationCheckerInterface $authorizationChecker */
$authorizationChecker = $this->getService('AuthorizationChecker');
$this->manager = new Manager(
$entityManager,
$fooService,
$baaService,
$authorizationChecker
);
Which results in the error:
ServiceNotFoundException: You have requested a non-existent service "AuthorizationChecker"
I first tried mocking the service, but without defining the result I got "null" and defining the result makes it quite useless for my tests, because I mock the user right already and want to test if they play together correctly with the rest of my code, so it is a kind of functional test, rather than a unit test.
If I create the AuthorizationChecker manually I have the same problem with the TokenStorageInterface and the AccessDecisionManagerInterface.
What is the best way to test my code?
What I did was creating a variation of mocks with closures. I really hoped I could avoid that. So it was a kind of middle way between really using the AuthorizationChecker and writing it again as a mock. However if anyone has a more satisfying solution that would be great.
My problem is that with every method I test I check different rights/roles, so just setting the mock to give back true
or false
isn't enough. What I have here is that I can set it up for two different Symfony roles in one go and there for I have 4 variations. 'FACH' and 'PERSON' are substrings of my role names. The whole role name would be something like PRESON_CREATE
This is what I did:
private function mockAuthorizationChecker(string $role, bool $person = false, bool $fach = false)
{
$this->authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
if ($person && $fach) {
$this->authorizationChecker
->method('isGranted')
->willReturnCallback(
function ($role) {
$isGranted = false;
if (strpos($role, 'FACH')) {
$isGranted = true;
}
if (strpos($role, 'PERSON')) {
$isGranted = true;
}
return $isGranted;
}
);
}
if ($person && !$fach) {
$this->authorizationChecker
->method('isGranted')
->willReturnCallback(
function ($role) {
$isGranted = false;
if (strpos($role, 'FACH')) {
$isGranted = false;
}
if (strpos($role, 'PERSON')) {
$isGranted = true;
}
return $isGranted;
}
);
}
if (!$person && $fach) {
$this->authorizationChecker
->method('isGranted')
->willReturnCallback(
function ($role) {
$isGranted = false;
if (strpos($role, 'FACH')) {
$isGranted = true;
}
if (strpos($role, 'PERSON')) {
$isGranted = false;
}
return $isGranted;
}
);
}
if (!$person && !$fach) {
$this->authorizationChecker
->method('isGranted')
->willReturnCallback(
function ($role) {
$isGranted = false;
if (strpos($role, 'FACH')) {
$isGranted = false;
}
if (strpos($role, 'PERSON')) {
$isGranted = false;
}
return $isGranted;
}
);
}
}