You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony如何在PHPUnit测试中注入AuthorizationChecker?

解决PHPUnit测试中AuthorizationChecker服务依赖问题

问题背景

同事修改了服务代码,新增了基于AuthorizationCheckerInterface的权限校验:

$this->authorizationChecker->isGranted(Roles::ROLE_PERSON_VIEW);

但测试代码未适配,当前测试通过以下方式创建待测试服务:

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
);

执行测试时抛出错误:

ServiceNotFoundException: You have requested a non-existent service "AuthorizationChecker"

尝试两种方案均存在问题:

  • 模拟AuthorizationCheckerInterface:未定义返回值时返回null,定义返回值则无法验证权限逻辑与业务代码的协同性(已模拟用户权限,需要真实校验逻辑)
  • 手动创建AuthorizationChecker:遇到TokenStorageInterface和AccessDecisionManagerInterface的依赖问题

最佳测试方案

方案1:使用正确的官方服务ID直接获取

Symfony中AuthorizationCheckerInterface对应的标准服务ID是security.authorization_checker,替换测试中的服务ID即可:

$authorizationChecker = $this->getService('security.authorization_checker');

配合测试中已模拟的用户Token(比如通过$this->loginUser($user)方法设置登录用户),就能完整验证权限逻辑与业务代码的协同性,无需额外配置依赖。

方案2:手动构建带真实逻辑的AuthorizationChecker

如果需要更灵活的控制,可手动构建依赖链,保留真实权限校验逻辑的同时使用自定义Token:

  1. 模拟TokenStorage并注入已准备好的用户Token:
$tokenStorage = $this->createMock(TokenStorageInterface::class);
$tokenStorage->method('getToken')->willReturn($yourMockedToken); // $yourMockedToken为你已模拟的用户Token
  1. 从容器获取真实的权限决策管理器:
$accessDecisionManager = $this->getService('security.access.decision_manager');
  1. 实例化真实的AuthorizationChecker:
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;

$authorizationChecker = new AuthorizationChecker(
    $tokenStorage,
    $accessDecisionManager,
    $this->getService('security.authentication.trust_resolver')
);

此方案既保留了Symfony原生的权限校验逻辑,又能完全控制测试用的用户权限。

方案3:基于WebTestCase的功能测试适配

如果是功能测试场景,直接使用WebTestCase的内置方法简化流程:

$client = static::createClient();
$client->loginUser($yourTestUser); // 设置测试登录用户

$authorizationChecker = $client->getContainer()->get('security.authorization_checker');
$this->manager = new Manager(
    $entityManager,
    $fooService,
    $baaService,
    $authorizationChecker
);

loginUser方法会自动将用户Token注入容器的授权服务,无需手动处理依赖。

内容的提问来源于stack exchange,提问作者Calamity Jane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 08:47:11