Невозможно войти через тесты PHPUnit с Symfony 4 - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь запустить простой тест аутентификации, используя PHPUnit с Symfony 4, чтобы проверить, успешно ли пользователь вошел в систему. Я выполнил документацию для запуска теста аутентификации. Страница /admin будет автоматически перенаправлена ​​на /login, если пользователь не вошел в систему.

Я получаю эту ошибку при запуске теста:

There was 1 failure:

1) App\Tests\AuthTest::testAdminPanel
Failed asserting that 302 is identical to 200.

~ конфиг / пакеты / тест / security.yaml:

security:
    firewalls:
        main:
            http_basic: ~

Тест:

   public function testAdminPanel() {
        $client = static::createClient(array(), array(
            'PHP_AUTH_USER' => 'username',
            'PHP_AUTH_PW'   => 'password',
        ));

        $crawler = $client->request('GET', '/admin');

        $this->assertSame(Response::HTTP_OK, $client->getResponse()->getStatusCode());

    }

Примечание. Учетная запись username вместе с паролем password существуют в базе данных.

Контроллер безопасности:

<?php

namespace App\Security;

use App\Form\LoginFormType;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;


/**
 * Class LoginFormAuthenticator
 * @package App\Security
 */
class LoginFormAuthenticator extends AbstractGuardAuthenticator
{
    /**
     * @var FormFactoryInterface
     */
    private $formFactory;
    /**
     * @var EntityManager
     */
    private $em;
    /**
     * @var RouterInterface
     */
    private $router;
    /**
     * @var UserPasswordEncoder
     */
    private $userPasswordEncoder;

    /**
     * LoginFormAuthenticator constructor.
     * @param FormFactoryInterface $formFactory
     * @param EntityManagerInterface $em
     * @param RouterInterface $router
     * @param UserPasswordEncoderInterface $userPasswordEncoder
     */
    public function __construct(FormFactoryInterface $formFactory, EntityManagerInterface $em, RouterInterface $router, UserPasswordEncoderInterface $userPasswordEncoder)
    {
        $this->formFactory = $formFactory;
        $this->em = $em;
        $this->router = $router;
        $this->userPasswordEncoder = $userPasswordEncoder;
    }

    /**
     * @return string
     */
    protected function getLoginUrl()
    {
        return $this->router->generate('login');
    }

    /**
     * @param Request $request
     * @return bool
     *
     * Called on every request to decide if this authenticator should be
     * used for the request. Returning false will cause this authenticator
     * to be skipped.  Current implementation checks that this request method is POST and
     * that the user is on the login page.
     *
     */
    public function supports(Request $request)
    {
        return ($request->attributes->get('_route') === 'login' && $request->isMethod('POST'));
    }

    /**
     * @param Request $request
     * @param AuthenticationException|null $authException
     * @return RedirectResponse|Response
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {

        return new RedirectResponse($this->router->generate('login'));
    }

    /**
     * @param Request $request
     * @return bool|mixed
     */
    public function getCredentials(Request $request)
    {
        $form = $this->formFactory->create(LoginFormType::class);
        $form->handleRequest($request);
        $data = $form->getData();
        $request->getSession()->set(
            Security::LAST_USERNAME,
            $data['username']
        );

        return $data;
    }

    /**
     * @param mixed $credentials
     * @param UserProviderInterface $userProvider
     * @return null|object|UserInterface
     */
    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $username = $credentials['username'];

        $user =  $this->em->getRepository('App:User')->findOneBy(['username' => $username]);
        if(empty($user)) {
            $user = $this->em->getRepository('App:User')->findOneBy(array('email' => $username));
        }

        return $user;
    }

    /**
     * @param mixed $credentials
     * @param UserInterface $user
     * @return bool
     */
    public function checkCredentials($credentials, UserInterface $user)
    {
        $password = $credentials['password'];

        if($this->userPasswordEncoder->isPasswordValid($user, $password)) {
            return true;
        }

        return false;
    }

    /**
     * @return string
     */
    public function getDefaultSuccessRedirectUrl()
    {
        return $this->router->generate('default');

    }

    /**
     * @param Request $request
     * @param AuthenticationException $exception
     * @return RedirectResponse
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);

        return new RedirectResponse($this->router->generate('login'));

    }

    /**
     * @param Request $request
     * @param TokenInterface $token
     * @param string $providerKey
     * @return null|RedirectResponse|Response
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        $user = $token->getUser();
        $user->setLastLogin(new \DateTime('now'));
        $this->em->persist($user);
        $this->em->flush();

        return new RedirectResponse($this->router->generate('easyadmin'));
    }

    /**
     * @return bool
     */
    public function supportsRememberMe()
    {
        return false;
    }
}

1 Ответ

0 голосов
/ 20 сентября 2018

ваш тест выглядит нормально. HTTP 302 означает перенаправление, мы обычно перенаправлены после успешного входа в систему.

попробуйте добавить $client->followRedirects(); как предложено в https://symfony.com/doc/current/testing#redirecting

...