For the complete documentation index, see llms.txt. This page is also available as Markdown.

Testing

The component ships the test tooling it uses itself, under AccessControl\Test and AccessControl\Bundle\Test. It is published on purpose: asserting that a door was closed, and which door, is not something an application should have to rebuild.

Asserting on an answer you hold

AccessOutcomeAssertionsTrait matches an AccessOutcome or an AccessDecision you have in your hand.

use AccessControl\Test\AccessOutcomeAssertionsTrait;

final class PostVoterTest extends TestCase
{
    use AccessOutcomeAssertionsTrait;

    public function testTheAuthorMayEdit(): void
    {
        $outcome = new PostVoter()->vote(new AccessRequest($author, 'EDIT', $post));

        self::assertAccessGranted($outcome);
    }
}
Assertion

assertAccessGranted($answer)

assertAccessDenied($answer)

assertAccessAbstained($answer)

An abstention is a result of its own, so assert it rather than settling for "not granted"

Asserting on a request that has run

AccessControlAssertionsTrait matches the questions a functional test asked, not an answer you hold. A 403 says the door was closed; these say which door, and why.

Assertion

assertAccessWasDeniedOn($attribute)

assertAccessWasGrantedOn($attribute)

assertAccessWasNotDeniedOn($attribute)

assertAccessWasDeniedBy($voter)

Which voter closed the door

assertAccessDecisionCount($count)

Catches a question asked twice, or not at all

getAccessDecisionEvents()

The whole log, to assert on something the others do not cover

The two traits are named apart on purpose: AccessOutcomeAssertionsTrait is about an answer in your hand, AccessControlAssertionsTrait about a request that has run.

When an assertion fails, it lists every decision that was reached, with its reason. "No access decision was reached at all" is its own message, because a controller with no access policy and an entry point whose listener is not registered both look like that.

Testing a policy handler

AccessPolicyHandlerTestTrait gives a handler two tests for free and a way to evaluate a policy without a container.

The two inherited tests check that the handler claims the policies it says it handles, and that it leaves a foreign one to another handler. FixedOutcomeAccessPolicy is a policy that answers what you tell it to, so a composite can be tested without writing voters.

Testing a combining algorithm

AccessDecisionStrategyTestTrait runs a table of voter outcomes through a strategy.

Watching without the framework

Everything above reads the events the manager dispatches. Give the manager a dispatcher, collect AccessDecisionEvent, and you have the same log outside any framework. See The Manager.

Last updated

Was this helpful?