Closed FabRiviere closed 1 year ago
symfony composer req phpunit --dev
symfony console make:test TestCase SpamCheckerTest
<?php
namespace App\Tests;
use App\Entity\Comment;
use App\Service\SpamChecker;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
class SpamCheckerTest extends TestCase
{
public function testSpamScoreWithInvalidRequest(): void
{
$comment = new Comment();
$comment->setCreatedAtValue();
$context = [];
// ! La classe MockHttpClient permet de simuler un serveur HTTP.On lui donne un tableau d'instance MockResponse contenant le corps et en-têtes de réponse attendus.
$client = new MockHttpClient([new MockResponse('invalid', ['response_headers' => ['x-alismet-debug-help: Invalid key']])]);
$checker = new SpamChecker($client, 'abcde');
// ! Appel de la méthode getSpamScore et vérifiaction qu'une exception est levée via la méthode expectException de PHPUnit.
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Unable to check for spam : invalid (Invalid key).');
$checker->getSpamScore($comment, $context);
}
}
// ! Les data providers de PHPUnit permettent de réutiliser la même logique pr plusieurs scénarios
/**
* @dataProvider provideComments
*/
public function testSpamScore(int $expectedScore, ResponseInterface $response, Comment $comment, array $context)
{
$client = new MockHttpClient([$response]);
$checker = new SpamChecker($client, 'abcde');
$score = $checker->getSpamScore($comment, $context);
$this->assertSame($expectedScore, $score);
}
public static function provideComments(): iterable
{
$comment = new Comment();
$comment->setCreatedAtValue();
$context = [];
$response = new MockResponse('', ['response_headers' => ['x-akismet-pro-tip: discard']]);
yield 'blatant_spam' => [2, $response, $comment, $context];
$response = new MockResponse('true');
yield 'spam' => [1, $response, $comment, $context];
$response = new MockResponse('false');
yield 'ham' => [0, $response, $comment, $context];
}
Création d'un dossier Controller dans le dossier tests et nouveau fichier ConferenceControllerTest.php
<?php
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class ConferenceControllerTest extends WebTestCase
{
public function testIndex()
{
$client = static::createClient();
$client->request('GET', '/');
$this->assertResponseIsSuccessful();
$this->assertSelectorTextContains('h2', 'Give your feedback');
}
}
symfony console secrets:set AKISMET_KEY --env=test
On tape ensuite notre clé d'API Akismet.
symfony console doctrine:database:create --env=test
symfony console doctrine:migrations:migrate -n --env=test
Installation du package Doctrine Fixtures :
symfony composer req orm-fixtures --dev
Modification du fichier AppFixtures.php généré par le package
<?php
namespace App\DataFixtures;
use App\Entity\Admin;
use App\Entity\Comment;
use App\Entity\Conference;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactoryInterface;
class AppFixtures extends Fixture
{
public function __construct(private PasswordHasherFactoryInterface $passwordHasherFactory)
{
}
public function load(ObjectManager $manager): void
{
$amsterdam = new Conference();
$amsterdam->setCity('Amsterdam');
$amsterdam->setYear('2019');
$amsterdam->setIsInternational(true);
$manager->persist($amsterdam);
$paris = new Conference();
$paris->setCity('Paris');
$paris->setYear('2020');
$paris->setIsInternational(false);
$manager->persist($paris);
$comment1 = new Comment();
$comment1->setConference($amsterdam);
$comment1->setAuthor('Fabien');
$comment1->setEmail('fabien@example.com');
$comment1->setText('This is a great conference.');
$manager->persist($comment1);
$admin = new Admin();
$admin->setRoles(['ROLE_ADMIN']);
$admin->setUsername('Fabsolo');
$admin->setEmail('fabsolo@email.fr');
$admin->setPassword($this->passwordHasherFactory->getPasswordHasher(Admin::class)->hash('azerty'));
$admin->setFirstname('Fab');
$admin->setLastname('Solo');
$admin->setIsVerified(1);
$manager->persist($admin);
$manager->flush();
}
}
symfony console doctrine:fixtures:load --env=test
Ajout d'une méthode dans le ConferenceControllerTest.php
public function testConferencePage()
{
$client = static::createClient();
// ! On retourne 1 instance de crawler qui aide à trouver des éléments sur la page.
$crawler = $client->request('GET', '/');
// ! On vérifie qu'on a bien 2 conférences listées sur la page.
$this->assertCount(2, $crawler->filter('h4'));
// ! On clique sur le view -> le premier qu'il trouve.
$client->clickLink('View');
// ! On vérifie le titre de la page et que la réponse est le h2 pour être sur d'être sur la bonne page.
$this->assertPageTitleContains('Amsterdam');
$this->assertResponseIsSuccessful();
$this->assertSelectorTextContains('h2', 'Amsterdam 2019');
// ! On vérife qu'il y a 1 commentaire sur la page.
$this->assertSelectorExists('div:contains("There are 1 comments")');
}
On peut ensuite vérifier que le nouveau test passe :
symfony php bin/phpunit tests/Controller/ConferenceControllerTest.php
Ajout d'une méthode dans le ConferenceControllerTest.php
public function testCommentSubmission()
{
$client = static::createClient();
$client->request('GET', '/conference/amsterdam-2019');
$client->submitForm('Submit', [
'comment_form[author]' => 'Fabien',
'comment_form[text]' => 'Some feedback from an automated functional test',
'comment_form[email]' => 'me@automat.ed',
'comment_form[photo]' => dirname(__DIR__, 2). '/public/images/under-construction.gif',
]);
$this->assertResponseRedirects();
$client->followRedirect();
$this->assertSelectorExists('div:contains("There are 2 comments")');
}
On peut ensuite vérifier que le nouveau test passe :
symfony php bin/phpunit tests/Controller/ConferenceControllerTest.php