O fato de uma pessoa conseguir iniciar sessão não demonstra que ela está autorizada a consultar ou modificar todos os dados da aplicação. A autenticação identifica o usuário; a autorização decide o que ele pode fazer, sobre qual recurso e sob quais condições. Uma rota pode exigir uma sessão válida e, ainda assim, permitir que alguém leia o pedido de outra conta se a relação entre usuário e recurso não for verificada.
Os testes de autorização em PHP devem verificar esse limite a partir dos pontos de entrada usados pela aplicação: por exemplo, uma requisição HTTP a uma rota web ou a uma API. O objetivo não é testar como um framework implementa suas políticas, mas confirmar o comportamento observável: quem pode fazer o quê, quando a solicitação é rejeitada e quais dados permanecem intactos.
Traduzir as regras de acesso em uma matriz

Antes de escrever testes, expresse as regras com quatro elementos: ator, ação, recurso e contexto. O contexto inclui condições que alteram a permissão, como pertencer à mesma organização, ser proprietário do registro ou ter determinado estado. Essa estrutura evita reduzir a autorização a uma lista de papéis.
- Ator: usuário anônimo, membro, responsável ou administrador.
- Ação: consultar, criar, editar, excluir ou aprovar.
- Recurso: um pedido, documento, conta ou outro objeto protegido.
- Contexto: proprietário, organização, estado do recurso ou relação vigente.
Por exemplo, uma regra pode permitir que um membro consulte seus próprios pedidos, enquanto um responsável consulta os da sua organização. Um administrador poderia ter acesso mais amplo, sujeito às regras reais do produto. A matriz transforma cada frase de negócio em casos verificáveis e torna visíveis as combinações ausentes.
Não é necessário testar todas as permutações imagináveis. Priorize os limites de confiança: um usuário sem sessão, dois usuários da mesma organização, usuários de organizações diferentes, uma pessoa com um papel privilegiado e um recurso que não lhe pertence. Acrescente contextos especiais que alterem a decisão, como um pedido arquivado, caso suas permissões sejam diferentes das de um pedido ativo.
Preparar cenários de integração representativos
Prepare os dados de forma explícita e enxuta. Um teste típico pode criar duas organizações, um usuário em cada uma e um recurso associado a uma delas. Em seguida, autentique como o usuário que tenta acessar e faça uma requisição à rota pública da aplicação, usando o identificador do recurso. Assim, são exercitados em conjunto a entrada, a autenticação, a autorização e a resposta.
Para cada regra importante, inclua pelo menos um caso permitido e um caso rejeitado. Se o usuário proprietário puder editar um recurso, verifique se a edição autorizada funciona e se outro usuário não consegue repeti-la. Um caso positivo é essencial: uma suíte que só espera rejeições poderia passar mesmo que a aplicação também bloqueasse quem tem permissão.
Verifique também o recurso inexistente. A resposta a um identificador desconhecido pode ser diferente da resposta a um identificador existente sem permissão. Algumas aplicações usam uma resposta de não encontrado para não revelar a existência do recurso; outras informam que o acesso é proibido. O teste deve refletir a política deliberada do produto, não impor uma convenção universal.
Use factories, construtores de fixtures ou helpers de teste que produzam estados válidos e legíveis. Evite depender de identificadores fixos, da ordem de execução ou de dados compartilhados que outro teste possa modificar. Se a persistência fizer parte do comportamento que você quer verificar, confirme o resultado no banco de dados usando as ferramentas habituais do projeto; não presuma que uma resposta de sucesso garante, por si só, o estado correto.
Testar o isolamento entre usuários e organizações
O isolamento merece casos próprios porque os erros costumam surgir quando se altera um identificador na URL ou no corpo da requisição. Crie um recurso de uma conta e tente consultá-lo, editá-lo ou excluí-lo usando outra identidade. Repita a verificação entre organizações quando a aplicação tiver escopos de dados por empresa. Para operações críticas, teste cada ação: proteger uma leitura não demonstra que o download, a exportação ou a atualização também estejam protegidos.
Para não duplicar toda a suíte, compartilhe a preparação comum e parametrize apenas as dimensões que expressam a regra. Por exemplo, uma lista de pares ator-recurso pode definir quais combinações são permitidas. Mantenha nomes concretos para os casos: “membro de outra organização não pode editar o pedido” explica mais do que um conjunto opaco de valores booleanos. Separe os cenários quando o método, a rota ou os efeitos esperados forem diferentes.
Evite testar cada combinação de papéis com cada recurso se muitas delas não representarem regras distintas. Em vez disso, identifique equivalências justificadas e mantenha casos explícitos para exceções e limites. Se houver papéis hierárquicos, não presuma que um herda automaticamente todas as permissões de outro: verifique a regra efetiva definida pelo produto.
Verificar respostas e efeitos colaterais
Em caso de rejeição, verifique tanto a resposta quanto se a operação protegida não foi executada. Dependendo da interface, a resposta pode ser um redirecionamento, uma resposta com status de não autorizado ou proibido, ou uma resposta de recurso não encontrado. Verifique o contrato relevante — status, formato e, quando importante, mensagem — sem acoplar o teste a detalhes de apresentação desnecessários.
Em uma atualização rejeitada, verifique se os campos sensíveis continuam iguais. Em uma exclusão, confirme que o registro continua disponível. No caso de uma operação que gera uma fatura, uma notificação ou um evento, verifique também se esse efeito não ocorreu. As asserções devem abranger os efeitos importantes para o negócio, não apenas o código HTTP.
Uma requisição não autorizada também não deve permitir alterações parciais. Se o fluxo executar várias operações, verifique se a rejeição ocorre antes das mutações ou se a transação deixa o sistema em um estado coerente. Não é necessário inspecionar métodos privados para demonstrá-lo: observe a resposta e os dados ou efeitos persistidos.
Manter testes resistentes a alterações de implementação
Os testes de integração devem passar por uma interface estável da aplicação, como uma rota e uma requisição com a identidade autenticada pelos mecanismos de teste disponíveis. Evite chamar diretamente uma classe interna de políticas se o que você pretende validar é o acesso real a um recurso: isso poderia deixar de cobrir o registro da rota, o middleware ou a forma como o objeto é carregado.
Ao mesmo tempo, não transforme a suíte em uma réplica de toda a aplicação. Teste o contrato de autorização em pontos representativos e reserve os testes unitários para regras puras que precisem de muitos casos de contexto. Essa combinação ajuda a localizar falhas: um teste de regra pode isolar uma condição, enquanto o teste de integração confirma que essa regra protege o fluxo exposto.
Quando os papéis, as rotas ou as políticas mudarem, revise a matriz antes de alterar as expectativas. Um teste atualizado apenas para aceitar o novo resultado pode ocultar uma ampliação acidental das permissões. Registre por que a regra mudou, identifique quais atores passam a ter ou deixam de ter acesso e acrescente casos que protejam os novos limites.
Lista de verificação para revisar uma alteração

- Estão definidos o ator, a ação, o recurso e o contexto?
- Existe pelo menos um cenário permitido e um rejeitado para a regra afetada?
- O acesso entre usuários ou escopos de dados é testado quando aplicável?
- O recurso inexistente é coberto, assim como a política escolhida para não revelar informações?
- A requisição passa pelo ponto de entrada que deve estar protegido?
- É verificado que uma rejeição não altera dados nem gera efeitos colaterais?
- Os dados de teste são isolados, legíveis e reproduzíveis?
- As expectativas refletem uma decisão do produto e não um detalhe acidental do framework?
Uma suíte útil não demonstra que “existem permissões” em abstrato: demonstra que as combinações relevantes funcionam e que as não autorizadas não ultrapassam o limite. Manter essa matriz junto de testes de integração concretos facilita revisar alterações de acesso sem vincular a segurança a uma implementação interna específica.



