Cześć,
chciałbym wykonać testowanie rejestracji i logowania w Symfony.
Symfony -> w katalogu tests/Controller/ utworzyłem plik SecurityControllerTest.php (test logowania),
gdzie chciałbym uzupełnic formularz danymi i zalogować użytkownika, następnie sprawdzić, czy jest zalogowany.
Napisałem taki kod, ale ciągle sypie errorami (coś tu rzeźbię)?
<?php declare(strict_types=1); namespace App\Tests\Controller; use App\Repository\UserRepository; use App\Tests\Integration\AbstractIntegrationWebTestCase; class SecurityControllerTest extends AbstractIntegrationWebTestCase { public const TEST_USER_LOGIN = 'test@domain.com'; public const TEST_USER_PASSWORD = 'test123'; public function testLogin(): void { $client = http://www.php.net/static::createClient(); $crawler = $client->request('GET', '/login'); // Uzupelnij formularz danymi i zaloguj $dataLogin = [ 'email' => self::TEST_USER_LOGIN, 'password' => self::TEST_USER_PASSWORD, //'submit' => 'Login', ]; //$formLogin = $crawler->filter('form')->form(); $formLogin = $crawler->selectButton('Login')->form(); //$formLogin['email']->setValue(self::TEST_USER_LOGIN); //$formLogin['password']->setValue(self::TEST_USER_PASSWORD); //$formLogin['submit']->setValue('Login'); // OFF $formLogin['_csrf_token"'] = 'It is generated automatically!'; //$client->submit($formLogin, $dataLogin); //dd($client->getRequest()->request); // Sprawdz, czy zalogowany -> sprawdza tylko czy email jest w bazie ? $repositoryUser = http://www.php.net/static::getContainer()->get(UserRepository::class); $testUser = $repositoryUser->findOneBy(['email' => self::TEST_USER_LOGIN]); $client->loginUser($testUser); //dd($testUser); $this->assertResponseIsSuccessful(); } }
A pokaż Twig i Kontroler dla routa /login?
Która wersja Symfony? Masz w kodzie
więc zakładam, że 5.1+
$client->loginUser($testUser);
$repositoryUser = http://www.php.net/static::getContainer()->get(UserRepository::class); $testUser = $repositoryUser->findOneBy(['email' => self::TEST_USER_LOGIN]); $client->loginUser($testUser);
$client = http://www.php.net/static::createClient(); $crawler = $client->request('GET', '/login'); // Uzupelnij formularz danymi i zaloguj $dataLogin = [ 'email' => self::TEST_USER_LOGIN, 'password' => self::TEST_USER_PASSWORD, //'submit' => 'Login', ]; //$formLogin = $crawler->filter('form')->form(); $formLogin = $crawler->selectButton('Login')->form(); $formLogin['email'] = self::TEST_USER_LOGIN; $formLogin['password'] = self::TEST_USER_PASSWORD; $this->client->submit($formLogin);
// BTW. dodaj sobie router i generuj sciezki zamiast wstawiac je na sztywno $router = http://www.php.net/static::getContainer()->get(UrlGeneratorInterface::class); $this->assertResponseRedirects($router->generate('app_home'));
$client->request('GET', '/home'); $this->assertResponseIsSuccessful(); $this->assertSelectorTextContains('h1', 'Witaj');
[topic=0]oken"</span> <span class="kw3">name</span><span class="sy0">=</span><span class="st0">"_csrf_token"</span> <span class="kw3">value</span><span class="sy0">=</span><span class="st0">"97e..."</span> <span class="sy0">/</span>><<span class="sy0">/</span>http://</span>http<span%20class="sy0">:</span><span%20class="co1">//december.com/html/4/element/div.html></span></div><li class="li2"><div class="de2"><span class="sc2"><<span class="sy0">/</span>http://december.com/html/4/element/form.html></span></div> [/list]<div class="foot">[HTML] [url="./Pobierz-Plik-502620.html"]plaintext[/url] </div></pre><!--/Geshi:502620:html--> <!--quoteo(post=1261873:http://www.php.net/date=21.09.2023, 12:28:23 :name=jacek.e3)--><div class='quotetop'>Cytat(jacek.e3 @ 21.09.2023, 12:28:23 ) [snapback]1261873[/snapback]</div><div class='quotemain'><!--quotec-->Która wersja Symfony?<!--QuoteEnd--></div><!--QuoteEEnd--> Symfony w wersji 5.4 Przesłany kod już wcześniej sprawdzałem, ale wg. tego co napisałeś teraz jest tak: [php]class SecurityControllerTest extends AbstractIntegrationWebTestCase { public const TEST_USER_LOGIN = 'test@email.com'; public const TEST_USER_PASSWORD = 'Test123'; public function testLogin(): void { $client = http://www.php.net/static::createClient(); $crawler = $client->request('GET', '/login'); $formLogin = $crawler->selectButton('Login')->form(); $formLogin['email'] = self::TEST_USER_LOGIN; $formLogin['password'] = self::TEST_USER_PASSWORD; $client->submit($formLogin); $router = http://www.php.net/static::getContainer()->get(UrlGeneratorInterface::class); $this->assertResponseRedirects($router->generate('app_main')); //dd($client->getResponse()->getContent()); } }
3 sprawy:
1) jak się logujesz "ręcznie" - to działa?
2) kolega prosił o twiga formularza i kod kontrolera. Nie chodziło nam o wygenerowany kod w htmlu tylko o surowe pliki z twiga i klase controllera.
Formularz powinien mieć dynamicznie generowany token csrf:
<http://december.com/html/4/element/input.html type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}" >
$error = $authenticationUtils->getLastAuthenticationError();
Sprawy
1. Tak, wypełniam pole login, hasło, zaznaczam Agree terms i loguje się.
2. Przesłałem wygenerowany kod HTML, ponieważ tu wszystko widać i jest też token csrf
<http://december.com/html/4/element/input.html type="hidden" id="_csrf_token" name="_csrf_token" value="abc..." />
class SecurityControllerTest extends AbstractIntegrationWebTestCase { public const TEST_USER_LOGIN = 'test@email.com'; public const TEST_USER_PASSWORD = 'Test123'; public function testLogin(): void { $client = http://www.php.net/static::createClient(); $crawler = $client->request('GET', '/login'); $formLogin = $crawler->selectButton('Login')->form(); $formLogin['email'] = self::TEST_USER_LOGIN; $formLogin['password'] = self::TEST_USER_PASSWORD; $client->submit($formLogin); $router = http://www.php.net/static::getContainer()->get(UrlGeneratorInterface::class); $this->assertResponseRedirects($router->generate('app_main')); } }
Cały czas chodzilo o kontroler do logowania, a nie klase do testowania.
Jeżeli nie ma tam nic innego przy tym failure to w takim razie może wszystko jest tam ok. W zależności od wersji phpunit były różne defaultowe zachowania co zrobić z deprecation errorami.
Zobacz tu: https://symfony.com/doc/current/components/phpunit_bridge.html#disabling-the-deprecation-helper
<env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled" />
Ten kontroler podałem w [PHP] pobierz, plaintext ale coś się tu poprzestawiało przy wyświetlaniu, stąd zmyłka (wiem, że podałem kod kontrolera, ale faktycznie gdzieś zaginął w akcji).
Jeśli jest error to raczej nie jest wszystko ok. Zobaczę co pod tym linkiem piszą.
Dodałem
<!-- phpunit.xml.dist --> <listeners> <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener"> <arguments> <array> <element key="debug-class-loader"><integer>0</integer></element> </array> </arguments> </listener> </listeners>
ok, ale jak kontrolera nie było tak dalej nie ma.
W końcu jest za to jakiś konkret. Dostajesz info, że adres strony nie zgadza się z adresem przekierowania. Do tego gdzieś tam wcześniej pisałeś, że content robi redirect na /login
Pamiętasz to?
$error = $authenticationUtils->getLastAuthenticationError();
Testuje, sprawdzam itp., ale coś to testowanie idzie jak krew z nosa
Klasa kontrolera
class SecurityController extends AbstractController { #[Route(path: '/login', name: 'app_login')] public function login(AuthenticationUtils $authenticationUtils): Response { if ($this->getUser()) { return $this->redirectToRoute('app_main'); } $error = $authenticationUtils->getLastAuthenticationError(); if (http://www.php.net/isset($error)) { $this->addFlash('danger', $error->getMessage()); } $form = $this->createForm(LoginType::class, [ 'email' => $authenticationUtils->getLastUsername(), ]); return $this->render('security/login.html.twig', [ 'form' => $form->createView(), 'error' => $error, ]); } // and more... }
Masz route "app_main"?
Masz usera w bazie testowej?
Spróbuj dodać to dump($error) w kontrolerze i odpal test jeszcze raz;
Mam route 'app_main'
$router = static::getContainer()->get(UrlGeneratorInterface::class);
$this->assertResponseRedirects($router->generate('app_main'));
User jest bazie projektu, a że jest jedna baza to też jest w testowej! Chyba?
Dodaje dump($error) w kontrolerze SecurityController i odpalam test jeszcze raz,
otrzymuję null z dumpa i błąd... wcześniej wymieniony
Kontroler test
class SecurityControllerTest extends AbstractIntegrationWebTestCase { public const TEST_USER_LOGIN = 'test@email.com'; public const TEST_USER_PASSWORD = 'Test123'; public function testLogin(): void { $client = http://www.php.net/static::createClient(); $crawler = $client->request('GET', '/login'); $formLogin = $crawler->selectButton('Login')->form(); $formLogin['email'] = self::TEST_USER_LOGIN; $formLogin['password'] = self::TEST_USER_PASSWORD; $client->submit($formLogin); $router = http://www.php.net/static::getContainer()->get(UrlGeneratorInterface::class); $this->assertResponseRedirects($router->generate('app_main')); } }
Masz jakis serwer z bazodanowy - mysql ?
Zaloguj się tam i wyświetl bazy danych. Sprawdź, czy jest tam baza danych z suffixem '_test'. Jak jest to wejdz do niej, sprawdz czy masz wszystkie tabele, a w szczegolnosci czy masz tabele z usarami i czy jest w niej rekord dotyczacy Twojego testowego konta.
Sprawdź to, nie zakładaj że to jest to samo.
defaultowy suffix do bazy w srodowisku testowy:
app/config/packages/doctrine.yaml
when@test: doctrine: dbal: # "TEST_TOKEN" is typically set by ParaTest dbname_suffix: '_test%env(default::TEST_TOKEN)%'
Ustawienia są tak zmienione, że powinno działać na bazie głównej (nie _test) i wygląda, że działa, ponieważ dla repozytorium podbiera dane z bazy bez problemu.
Przykład:
$userRepository = http://www.php.net/static::$container->get(UserRepository::class); $testUser = $userRepository->findOneBy(['email' => 'test@email.com']);
Kod
$userRepository = http://www.php.net/static::$container->get(UserRepository::class); $testUser = $userRepository->findOneBy(['email' => 'test@email.com']);
<server name="APP_ENV" value="test" force="true" />
W phpunit.xml.dis mam
<server name="APP_ENV" value="test" force="true" />
Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)