9. La Testabilité et la Pyramide des Tests : L’usage des repositories “In-Memory” pour des tests…
L’architecture hexagonale aligne le découpage du code avec le découpage des tests. Chaque couche a un régime de test approprié à sa nature…
9. La Testabilité et la Pyramide des Tests : L’usage des repositories “In-Memory” pour des tests ultra-rapides.
L’architecture hexagonale aligne le découpage du code avec le découpage des tests. Chaque couche a un régime de test approprié à sa nature. Le résultat : des tests rapides sur le domaine, des tests ciblés sur les cas d’usage, des tests d’intégration sur les adaptateurs critiques.
1. La pyramide et ses niveaux
[ E2E ] ← peu, lents, parcours critiques
[ Intégration ] ← adaptateurs Doctrine, S3, bus
[ Tests applicatifs ] ← handlers + faux adaptateurs InMemory
[ Tests de domaine ] ← PHP pur, pas de kernel, millisecondes
- Beaucoup de tests unitaires rapides sur le domaine (PHP pur, pas de kernel).
- Quelques tests applicatifs ciblés sur l’orchestration (handlers, avec de faux adaptateurs).
- Des tests d’intégration sur les adaptateurs critiques (Doctrine, stockage, bus).
- Peu de tests E2E, centrés sur les parcours critiques.
Plus on monte dans la pyramide (Domaine → E2E), plus le test est lent et coûteux à maintenir. Plus on descend, plus le feedback est rapide et la couverture ciblée.
2. Tests de domaine : PHP pur, sans kernel
Quand le domaine protège les invariants, il devient testable avec PHPUnit sans démarrer le kernel Symfony, sans base de données, sans aucun service externe.
final class DepositRequestTest extends TestCase
{
// Règle : on ne peut joindre une pièce qu'à un dossier encore en état DRAFT
public function testCannotAttachDocumentWhenNotDraft(): void
{
$depositRequest = DepositRequestMother::pending(); // déjà soumis, plus modifiable
$this->expectException(DepositRequestTransitionNotAllowedException::class);
$depositRequest->attachDocument(DepositRequestDocumentMother::valid($depositRequest));
}
// Règle : dès que toutes les pièces attendues sont jointes, le dossier passe automatiquement en PENDING
public function testBecomePendingWhenCompleteAfterDocumentAttached(): void
{
$depositRequest = DepositRequestMother::draftExpecting(1); // 1 pièce attendue, 0 jointe
$depositRequest->attachDocument(DepositRequestDocumentMother::valid($depositRequest));
self::assertSame(DepositRequestStatus::PENDING, $depositRequest->status);
$events = $depositRequest->releaseEvents();
self::assertCount(1, $events);
self::assertInstanceOf(DepositRequestBecamePendingEvent::class, $events[0]);
}
}
Ces tests s’exécutent en millisecondes. Pas de kernel Symfony, pas de Doctrine, pas de base de données. Tant que la règle métier ne change pas, le test reste vert même si toute l’infrastructure est remplacée.
3. Tests applicatifs : faux adaptateurs, pas de mocks profonds
Les handlers s’testent avec des implémentations en mémoire des ports. C’est plus lisible et plus stable que des mocks : on vérifie le comportement observable, pas l’ordre des appels internes.
final class InMemoryDepositRequestRepository implements DepositRequestRepositoryInterface
{
private array $items = [];
public function save(DepositRequest $depositRequest): void
{
$this->items[$depositRequest->id()->toString()] = $depositRequest;
}
public function get(DepositRequestId $id): DepositRequest
{
return $this->items[$id->toString()];
}
}
Ces faux adaptateurs se placent dans Infrastructure/Testing/. En test, le câblage change :
Production : Handler → DocumentStorageInterface → S3FlysystemAdapter
Test : Handler → DocumentStorageInterface → InMemoryDocumentStorage
Seul services_test.yaml change — pas une ligne dans le handler :
# config/services_test.yaml
App\DepositRequest\Application\Port\Out\DocumentStorageInterface:
alias: App\Tests\Behat\InMemoryDocumentStorage
Remarque sur le namespace : le port cible dans l’alias doit correspondre à l’emplacement réel de l’interface. DocumentStorageInterface est dans Application/Port/Out/, pas dans Domain/Port/Out/. Une erreur de namespace ici ne déclenche aucune erreur visible au démarrage — Symfony utilisera simplement l'implémentation réelle en test.
Le test vérifie l’orchestration du handler sans démarrer de base de données ni appeler S3.
4. Tests d’intégration : les adaptateurs face aux vraies ressources
Les adaptateurs de sortie doivent être testés avec de vraies ressources : Doctrine contre une vraie base PostgreSQL (pas SQLite), S3 contre un bucket de test, Messenger contre son transport réel si critique.
Ces tests vérifient que l’adaptateur respecte le contrat du port — qu’un save() suivi d'un get() retourne bien le même agrégat, que les mappings Doctrine correspondent au domaine.
5. Tests E2E : parcours critiques uniquement
Quand les niveaux inférieurs sont bien couverts, les tests E2E ne sont plus un filet de sécurité universel. Ils vérifient le câblage complet et les parcours critiques — pas les cas limites, qui sont couverts par les tests de domaine.
On en écrit moins, mais chacun a une raison d’être claire.
6. Le vrai bénéfice : refactorer sans peur
Le gain principal n’est pas la vitesse d’exécution. C’est la confiance de refactorer. Un test qui ne démolit pas à chaque changement d’implémentation, mais qui casse quand le comportement change — c’est un test utile.
Cette pyramide donne un feedback rapide sur les invariants, une vérification de l’orchestration, un contrôle des intégrations, et réduit la dépendance aux seuls tests bout en bout.
Conclusion
Chaque couche a son régime de test adapté à sa nature. Cette cohérence rend la qualité durable et le refactoring prévisible.
Comment cohabiter avec EasyAdmin sans laisser le CRUD contourner le domaine ? La fiche 10 présente le compromis.
메타데이터
- post_id
- ffdba41a6bc0
- slug
- 9-la-testabilité-et-la-pyramide-des-tests-lusage-des-repositories-in-memory-pour-des-tests-ffdba41a6bc0
- url
- https://medium.com/@ahmedbhs/9-la-testabilit%C3%A9-et-la-pyramide-des-tests-lusage-des-repositories-in-memory-pour-des-tests-ffdba41a6bc0
- canonical_url
- https://medium.com/@ahmedbhs/9-la-testabilit%C3%A9-et-la-pyramide-des-tests-lusage-des-repositories-in-memory-pour-des-tests-ffdba41a6bc0
- author_url
- https://medium.com/@ahmedbhs
- status
- ok
- fetched_at
- 2026-06-17 08:20:12