authorizationChecker->isGranted 在 phpUnit 测试中

authorizationChecker->isGranted in a phpUnit test

我目前正在为我的应用程序创建单元测试,但这是我第一次这样做。

我想测试这个功能:

/**
 * 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;
}

如您所见,第一个测试是检查用户是否拥有ROLE_USER。

当我尝试 "log my user" 时,我收到以下消息:

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

我尝试了在 Symfony 文档中找到的内容,但我一定遗漏了一些东西。这是我的测试 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" => 'Player11.Player11@test.com'));
        $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);
    }
}

我的 security.yml 看起来像:

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%'

我尝试连接我创建的用户与灯具。

我不确定我尝试这样做的方式,也许我走错了路,如果我错了请不要犹豫纠正我!

有关信息,我在 Symfony 3.2.13

祝你有美好的一天

WebTestCase 和您正在使用的 Symfony 文档中的示例应该用于控制器的功能测试。

您为客户端设置身份验证的方式正确。但是您没有使用该客户端向测试用例中的自举 Symfony 内核发出请求。您只是在手动创建的服务实例上进行简单的单元测试,这很好。

您只需使用 PHPUnit\Framework\TestCase 即可。

可以使用 WebTestCase 来测试您的服务,并在内核容器而不是客户端容器中覆盖 AuthorizationChecker 中使用的 TokenStorage,然后还可以从内核容器中获取您的服务,而不是自己实例化它。但我看不出有什么好处。无需测试 Symfony 组件(如果 isGranted 正在运行)。这在 Symfony 项目的范围内,很可能已经涵盖在那里。

你的错误

您出错的原因是无法模拟 final 方法。作为解决方法,您可以将 ApplicationChecker 构造函数中的依赖项设置为 AuthorizationCheckerInterface,然后从测试中的界面创建一个模拟。

$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
$authorizationChecker->method('isGranted')->willReturn(true);