feat: Ajoute tests entité et repository Account

Ajoute tests unitaires pour Account et AccountRepository,
et modifie la configuration de test et gitlab CI.
This commit is contained in:
Serreau Jovann
2025-07-16 16:32:27 +02:00
parent 3626704af3
commit 020de4b4c0
4 changed files with 250 additions and 1 deletions

View File

@@ -0,0 +1,119 @@
<?php
namespace App\Tests\Entity;
use App\Entity\Account;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class AccountTest extends TestCase
{
private ValidatorInterface $validator;
protected function setUp(): void
{
// Corrected line: Use enableAttributeMapping() for PHP attributes
$this->validator = Validation::createValidatorBuilder()
->enableAttributeMapping() // Use this for PHP attributes
->getValidator();
}
/**
* Helper to create a valid Account instance.
*/
private function createValidAccount(): Account
{
return (new Account())
->setUsername('testuser')
->setEmail('test@example.com')
->setPassword('securepassword')
->setUuid('1b9d67fe-1b0d-40e9-a417-36e6e2978051');
}
// --- Unit Tests for Getters and Setters ---
public function testGetId(): void
{
$account = new Account();
// ID is typically set by the ORM, so we can't directly test a generated value here.
// We'll rely on functional tests with the database for this.
$this->assertNull($account->getId());
}
public function testSetAndGetUsername(): void
{
$account = new Account();
$account->setUsername('newusername');
$this->assertSame('newusername', $account->getUsername());
}
public function testSetAndGetEmail(): void
{
$account = new Account();
$account->setEmail('newemail@example.com');
$this->assertSame('newemail@example.com', $account->getEmail());
}
public function testSetAndGetPassword(): void
{
$account = new Account();
$account->setPassword('hashedpassword');
$this->assertSame('hashedpassword', $account->getPassword());
}
public function testSetAndGetUuid(): void
{
$account = new Account();
$uuid = 'a1b2c3d4-e5f6-7890-1234-567890abcdef';
$account->setUuid($uuid);
$this->assertSame($uuid, $account->getUuid());
}
public function testSetAndGetRoles(): void
{
$account = new Account();
$account->setRoles(['ROLE_ADMIN', 'ROLE_USER']);
$this->assertContains('ROLE_ADMIN', $account->getRoles());
$this->assertContains('ROLE_USER', $account->getRoles());
$this->assertCount(2, $account->getRoles()); // Because ROLE_USER is guaranteed
}
// --- UserInterface and PasswordAuthenticatedUserInterface Tests ---
public function testGetUserIdentifier(): void
{
$account = $this->createValidAccount();
$this->assertSame('testuser', $account->getUserIdentifier());
}
public function testGetRolesAlwaysIncludesRoleUser(): void
{
$account = new Account();
$this->assertContains('ROLE_USER', $account->getRoles());
$account->setRoles(['ROLE_ADMIN']);
$this->assertContains('ROLE_ADMIN', $account->getRoles());
$this->assertContains('ROLE_USER', $account->getRoles());
$this->assertCount(2, $account->getRoles());
}
public function testEraseCredentials(): void
{
$account = $this->createValidAccount();
// eraseCredentials is deprecated and should not modify password directly in modern Symfony
// It's usually for clearing sensitive data from memory after security operations.
$account->eraseCredentials();
// Assert that password remains, as it's not actually cleared by this method (deprecated behavior)
$this->assertNotNull($account->getPassword());
}
public function testSerializeRemovesSensitiveData(): void
{
$account = $this->createValidAccount();
$serializedAccount = serialize($account);
$this->assertStringContainsString(hash('crc32c', 'securepassword'), $serializedAccount);
$this->assertStringNotContainsString('securepassword', $serializedAccount);
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace App\Tests\Repository;
use App\Entity\Account;
use App\Repository\AccountRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
/**
* Test class for AccountRepository.
*
* This class extends KernelTestCase to allow access to the Symfony container
* and test the repository methods with a real database connection (or mock it).
*/
class AccountRepositoryTest extends KernelTestCase
{
private ?EntityManagerInterface $entityManager;
private ?AccountRepository $accountRepository;
/**
* Sets up the test environment before each test method.
*
* This method boots the Symfony kernel and retrieves the EntityManager
* and AccountRepository from the service container. It also begins a database transaction
* to ensure a clean state for each test.
*/
protected function setUp(): void
{
// Boot the Symfony kernel to access services
self::bootKernel();
// Get the EntityManager from the container
// Corrected service name from 'doctrine.orm.entity.manager' to 'doctrine.orm.entity_manager'
$this->entityManager = static::getContainer()->get('doctrine.orm.entity_manager');
// Get the AccountRepository from the container
$this->accountRepository = static::getContainer()->get(AccountRepository::class);
// Begin a transaction to ensure a clean database state for each test.
// All changes made during the test will be rolled back in tearDown.
$this->entityManager->beginTransaction();
}
/**
* Tests the upgradePassword method with a valid Account instance.
*
* This test verifies that the password of an Account object is correctly
* updated and persisted when upgradePassword is called.
*/
public function testUpgradePassword(): void
{
// Create a mock Account entity for testing
$account = new Account();
$account->setEmail('test@example.com');
// Add a username as it seems to be a non-nullable field based on previous errors
$account->setUsername('test_user');
// Add a UUID in the correct format. For real applications, consider using a UUID library
// like Ramsey\Uuid (e.g., Uuid::uuid4()->toString()). For testing, a valid string literal is fine.
$account->setUuid('123e4567-e89b-12d3-a456-426614174000'); // Example of a valid UUID format
$account->setPassword('old_hashed_password'); // Set an initial password
$newHashedPassword = 'new_hashed_password';
// Call the upgradePassword method
$this->accountRepository->upgradePassword($account, $newHashedPassword);
// Assert that the account's password has been updated
$this->assertEquals($newHashedPassword, $account->getPassword(), 'The account password should be updated.');
// In a real test, you might want to mock the EntityManager's persist and flush calls
// to avoid actual database interaction if you're unit testing the repository in isolation.
// For an integration test with a real database, you'd check if the change is reflected
// by fetching the entity again.
// Example of how you might assert that persist and flush were called if mocking:
// $mockEntityManager = $this->createMock(EntityManagerInterface::class);
// $mockEntityManager->expects($this->once())->method('persist')->with($account);
// $mockEntityManager->expects($this->once())->method('flush');
// // Then inject this mock into your repository if it were a pure unit test.
}
/**
* Tests the upgradePassword method with an unsupported user type.
*
* This test verifies that an UnsupportedUserException is thrown when
* upgradePassword is called with a user object that is not an instance of Account.
*/
public function testUpgradePasswordWithUnsupportedUser(): void
{
// Expect an UnsupportedUserException to be thrown
$this->expectException(UnsupportedUserException::class);
// The message will contain the class name of the mock object, which implements the interface
// Create a mock object that implements PasswordAuthenticatedUserInterface
// but is NOT an instance of Account. This is crucial to trigger the UnsupportedUserException
// from the repository's internal check, rather than a TypeError from the method signature.
$unsupportedUserMock = $this->createMock(PasswordAuthenticatedUserInterface::class);
// Pass this mock object to the upgradePassword method.
$this->accountRepository->upgradePassword($unsupportedUserMock, 'some_password');
}
/**
* Cleans up the test environment after each test method.
*
* This method rolls back the database transaction started in setUp,
* effectively undoing any changes made during the test, and then closes
* the EntityManager to release database resources.
*/
protected function tearDown(): void
{
parent::tearDown();
// Check if a transaction is active before attempting to roll back
if ($this->entityManager && $this->entityManager->getConnection()->isTransactionActive()) {
$this->entityManager->rollback();
}
// Close the EntityManager to prevent memory leaks
if ($this->entityManager) {
$this->entityManager->close();
$this->entityManager = null; // Avoid memory leaks
}
$this->accountRepository = null;
}
}