fix(tests) : fiabilise la suite PHPUnit contre la derive d'horloge (ERP-98) (#47)
Auto Tag Develop / tag (push) Successful in 11s
Auto Tag Develop / tag (push) Successful in 11s
## Probleme (ERP-98) Suite PHPUnit flaky ~1 run sur 2 -> hook pre-commit qui plante, recours au `--no-verify` sur des commits sains. ## Cause racine Une seule cause commune : l'horloge `CLOCK_REALTIME` du conteneur n'est pas monotone sous WSL2/Docker (saut arriere sous charge), alors que le code et les tests supposaient une horloge stable. - **401 « Invalid JWT Token »** : lexik validait `iat`/`nbf`/`exp` avec `clock_skew: 0` (`LooseValidAt(.., PT0S)` cote lcobucci). Un recul d'horloge apres `/login_check` rend le token « dans le futur » -> rejet. - **Horodatages « meme seconde »** (`1780402904 > 1780402904`) : colonnes `TIMESTAMP(0)` + `sleep(1)` reel. L'ecart floor-seconde n'est nul que si l'horloge recule. ## Correctifs | Fichier | Modif | |---|---| | `config/packages/lexik_jwt_authentication.yaml` | `clock_skew: 15` -> tolere la derive (benefice prod aussi) | | `TimestampableBlamableSubscriber` | injection `ClockInterface` (prod inchange via NativeClock) | | `CategoryTimestampableBlamableTest` | `ClockSensitiveTrait` + MockClock fige/avance, suppression des `sleep(1)` | | `TimestampableBlamableSubscriberTest` | MockClock injecte dans les 4 instanciations | **Subtilite** : `mockTime()` cree un MockClock en UTC ; les colonnes `TIMESTAMP WITHOUT TIME ZONE` round-trippent via le fuseau PHP (Europe/Paris) -> decalage 2h. Le mock est seede dans le fuseau par defaut (comme le NativeClock prod). ## Verifications - `make test` : **464 tests verts**, 0 echec / 0 erreur - Test timestamp cible : **5/5 deterministe** (et plus rapide, sleeps reels supprimes) - `make php-cs-fixer-allow-risky` : 0 fichier a corriger - Deprecations/notices PHPUnit preexistantes (hors perimetre) Pas de migration, pas de changement front, RBAC intact. --------- Co-authored-by: admin malio <malio@yuno.malio.fr> Co-authored-by: Matthieu <contact@malio.fr> Reviewed-on: #47 Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
This commit was merged in pull request #47.
This commit is contained in:
@@ -14,6 +14,7 @@ use Doctrine\ORM\Event\PrePersistEventArgs;
|
||||
use Doctrine\ORM\Event\PreUpdateEventArgs;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\Clock\MockClock;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
@@ -30,7 +31,7 @@ final class TimestampableBlamableSubscriberTest extends TestCase
|
||||
public function testPrePersistWithUser(): void
|
||||
{
|
||||
$user = $this->createStub(UserInterface::class);
|
||||
$subscriber = new TimestampableBlamableSubscriber($this->securityReturning($user));
|
||||
$subscriber = new TimestampableBlamableSubscriber($this->securityReturning($user), new MockClock());
|
||||
$entity = new FullAuditableFixture();
|
||||
|
||||
$subscriber->prePersist($this->prePersistArgs($entity));
|
||||
@@ -45,7 +46,7 @@ final class TimestampableBlamableSubscriberTest extends TestCase
|
||||
|
||||
public function testPrePersistWithoutUser(): void
|
||||
{
|
||||
$subscriber = new TimestampableBlamableSubscriber($this->securityReturning(null));
|
||||
$subscriber = new TimestampableBlamableSubscriber($this->securityReturning(null), new MockClock());
|
||||
$entity = new FullAuditableFixture();
|
||||
|
||||
$subscriber->prePersist($this->prePersistArgs($entity));
|
||||
@@ -59,8 +60,13 @@ final class TimestampableBlamableSubscriberTest extends TestCase
|
||||
|
||||
public function testPreUpdate(): void
|
||||
{
|
||||
$user = $this->createStub(UserInterface::class);
|
||||
$subscriber = new TimestampableBlamableSubscriber($this->securityReturning($user));
|
||||
$user = $this->createStub(UserInterface::class);
|
||||
// Horloge figee 1s apres le createdAt simule : updatedAt doit avancer
|
||||
// de facon deterministe, sans dependre de l'heure reelle.
|
||||
$subscriber = new TimestampableBlamableSubscriber(
|
||||
$this->securityReturning($user),
|
||||
new MockClock(new DateTimeImmutable('2020-01-01 10:00:01')),
|
||||
);
|
||||
|
||||
// On simule une entite deja persistee : createdAt fige dans le passe,
|
||||
// createdBy positionne par une creation anterieure.
|
||||
@@ -80,7 +86,7 @@ final class TimestampableBlamableSubscriberTest extends TestCase
|
||||
public function testPartialEntityTimestampableOnly(): void
|
||||
{
|
||||
$user = $this->createStub(UserInterface::class);
|
||||
$subscriber = new TimestampableBlamableSubscriber($this->securityReturning($user));
|
||||
$subscriber = new TimestampableBlamableSubscriber($this->securityReturning($user), new MockClock());
|
||||
$entity = new TimestampableOnlyFixture();
|
||||
|
||||
// Entite Timestampable mais NON Blamable : seules les dates sont posees,
|
||||
|
||||
Reference in New Issue
Block a user