Tests Laravel avec Pest 5 en 2026 : TIA, Mocking et Questions d'Entretien
Maitrisez les bonnes pratiques de tests Laravel avec Pest 5, le Test Impact Analysis, Mockery, les fakes de facades et les tests d'architecture. Couvre les tests unitaires, tests fonctionnels, strategies de mocking et questions d'entretien courantes pour les developpeurs Laravel.

Les bonnes pratiques de testing Laravel ont evolue de maniere significative avec Pest 5, le moteur TIA (Test Impact Analysis) et PHPUnit 13. Laravel 13 integre un support Pest de premiere classe, rendant l'experience de test plus expressive et moins verbeuse que PHPUnit brut. Ce guide couvre les patterns essentiels pour les applications de production et les entretiens techniques.
Pest 5 (construit sur PHPUnit 13) est le framework de test par defaut de Laravel 13. Il necessite PHP 8.4+ et introduit le moteur TIA, la verification des agents IA en natif, l'integration PHPStan et le sharding equilibre par temps d'execution.
Configurer Pest 5 dans un Projet Laravel 13
Chaque nouvelle application Laravel 13 installe Pest automatiquement. Pour les projets existants, la migration depuis Pest 4 prend quelques minutes, la compatibilite PHPUnit 13 etant la principale consideration. La configuration reside dans tests/Pest.php, ou les traits globaux et les methodes helpers sont enregistres.
use Illuminate\Foundation\Testing\RefreshDatabase;
pest()
->extend(Tests\TestCase::class)
->use(RefreshDatabase::class)
->in('Feature');Ce fichier unique remplace l'ancien trait CreatesApplication et l'heritage de classe de base. Le trait RefreshDatabase encapsule chaque test dans une transaction de base de donnees, annulant automatiquement les modifications.
use App\Models\User;
it('registers a new user with valid data', function () {
$response = $this->postJson('/api/register', [
'name' => 'Jane Doe',
'email' => 'jane@example.com',
'password' => 'SecurePass123!',
'password_confirmation' => 'SecurePass123!',
]);
$response->assertStatus(201)
->assertJsonStructure(['user' => ['id', 'name', 'email']]);
expect(User::where('email', 'jane@example.com')->exists())->toBeTrue();
});L'API expect() de Pest se chaine naturellement avec les assertions PHPUnit. L'appel assertJsonStructure valide la forme de la reponse, tandis que expect()->toBeTrue() confirme l'etat de la base de donnees. Les deux styles coexistent sans conflit.
Test Impact Analysis : La Fonctionnalite Phare de Pest 5
Le moteur TIA est ce qui rend Pest 5 transformateur pour les grandes bases de code. Lors de la premiere execution, Pest enregistre quels tests touchent quels fichiers. Chaque execution suivante n'execute que les tests affectes par les modifications et rejoue les resultats en cache pour tout le reste.
# First run: records baseline (requires PCOV or Xdebug)
php artisan test
# Subsequent runs: only affected tests execute
php artisan testLa suite de tests de Laravel Cloud, contenant plus de 19 000 tests, est passee d'environ trois minutes a cinq secondes avec TIA active. Le moteur comprend plus que les fichiers PHP : il detecte les modifications dans les migrations, les templates Blade et les composants JavaScript partages.
TIA necessite un driver de couverture (PCOV ou Xdebug) pour enregistrer la reference initiale. Pour les pipelines CI, les mappings en cache persistent entre les executions, rendant le gain de performance cumulatif.
Tests Unitaires vs Tests Fonctionnels dans Laravel
La distinction entre tests unitaires et tests fonctionnels dans Laravel determine quelles parties du framework sont demarrees. Les tests unitaires s'executent sans le conteneur applicatif, les rendant plus rapides mais limites a la logique pure. Les tests fonctionnels demarrent l'application complete, permettant les appels HTTP, les requetes base de donnees et la resolution de services.
use App\Services\PriceCalculator;
describe('PriceCalculator', function () {
it('applies a percentage discount correctly', function () {
$calculator = new PriceCalculator();
// 20% off a 150.00 base price
$result = $calculator->applyDiscount(150.00, 20);
expect($result)->toBe(120.00);
});
it('rejects negative discount values', function () {
$calculator = new PriceCalculator();
expect(fn () => $calculator->applyDiscount(100.00, -5))
->toThrow(InvalidArgumentException::class);
});
});Les tests unitaires ciblent des classes isolees sans dependances externes. Le bloc describe regroupe les assertions liees, et Pest 5 supporte les blocs describe imbriques pour les hierarchies de tests complexes.
Les tests fonctionnels devraient representer la majorite d'une suite de tests Laravel. Ils detectent les bugs d'integration que les tests unitaires manquent, comme un middleware de route incorrect, des regles de validation manquantes ou des relations Eloquent defectueuses. Une regle courante : si le code touche la base de donnees, la couche HTTP ou une facade, ecrivez un test fonctionnel.
Strategies de Mocking avec les Facades et Mockery
Le mocking dans les tests Laravel isole le code sous test des dependances externes. Les facades Laravel fournissent des implementations fake integrees pour les queues, evenements, notifications, mails et storage. Mockery gere tout le reste.
use App\Models\Order;
use App\Models\User;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Queue;
use App\Mail\OrderConfirmation;
use App\Jobs\ProcessPayment;
it('dispatches payment job and sends confirmation email', function () {
// Fake both Mail and Queue facades
Mail::fake();
Queue::fake();
$user = User::factory()->create();
$order = Order::factory()->for($user)->create([
'total' => 99.99,
'status' => 'pending',
]);
// Act: confirm the order via HTTP
$this->actingAs($user)
->postJson("/api/orders/{$order->id}/confirm")
->assertOk();
// Assert: payment job was dispatched with correct amount
Queue::assertPushed(ProcessPayment::class, function ($job) use ($order) {
return $job->order->id === $order->id
&& $job->order->total === 99.99;
});
// Assert: confirmation email was sent to the user
Mail::assertSent(OrderConfirmation::class, function ($mail) use ($user) {
return $mail->hasTo($user->email);
});
});Les fakes de facades interceptent les appels au niveau du framework, empechant l'envoi reel d'emails ou le dispatch de jobs. Les assertions basees sur des closures verifient les donnees exactes passees a chaque composant.
Evitez de mocker les classes de domaine internes. Mockez aux frontieres : APIs tierces, mail, queues, systemes de fichiers. Le sur-mocking rend les tests fragiles et etroitement couples aux details d'implementation.
Pour les dependances qui ne sont pas des facades, injectez-les via le constructeur et utilisez Mockery :
use App\Services\PaymentGateway;
use App\Services\StripeClient;
it('charges the customer through the payment gateway', function () {
// Create a mock of the Stripe client
$stripeClient = Mockery::mock(StripeClient::class);
$stripeClient->shouldReceive('charge')
->once()
->with('cus_abc123', 5000, 'usd')
->andReturn(['status' => 'succeeded', 'id' => 'ch_xyz']);
// Bind the mock in the container
$this->app->instance(StripeClient::class, $stripeClient);
$gateway = app(PaymentGateway::class);
$result = $gateway->processCharge('cus_abc123', 50.00);
expect($result['status'])->toBe('succeeded');
});L'enregistrement du mock avec $this->app->instance() remplace l'implementation reelle pendant la duree du test. Mockery verifie que charge a ete appele exactement une fois avec les arguments attendus.
Tests d'Architecture avec les Presets Pest
Pest 5 inclut les tests d'architecture qui imposent des regles structurelles sur la base de code. Ces tests s'executent sur l'AST, pas au runtime, les rendant extremement rapides.
arch('controllers do not use Eloquent directly')
->expect('App\Http\Controllers')
->not->toUse('Illuminate\Database\Eloquent');
arch('services are final classes')
->expect('App\Services')
->toBeFinal();
arch('no debugging functions in production code')
->expect(['dd', 'dump', 'var_dump', 'ray'])
->not->toBeUsed();La premiere regle empeche les controleurs d'interroger directement la base de donnees, imposant un pattern de couche service. La seconde garantit que les services ne peuvent pas etre etendus, reduisant la complexite de l'heritage. La troisieme detecte les instructions de debug oubliees avant qu'elles n'atteignent la production.
Des presets specifiques a Laravel sont egalement disponibles :
arch()->preset()->laravel();
arch()->preset()->security();
arch()->preset()->php();Ces trois lignes imposent des dizaines de regles : les modeles etendent la bonne classe de base, les controleurs ne contiennent pas de logique metier, pas de fonctions non securisees comme eval() ou md5() pour le hachage, et les conventions PHP standard sont respectees.
Prêt à réussir tes entretiens Laravel ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Mutation Testing pour Verifier la Qualite des Tests
La couverture de code mesure quelles lignes s'executent pendant les tests. Le mutation testing va plus loin : il modifie le code source et verifie si les tests detectent le changement. Si une mutation survit, la suite de tests a une lacune.
# Run mutation testing on a specific class
php artisan test --mutate --class=App\\Services\\PriceCalculatorPest 5 introduit des mutations comme changer > en >=, supprimer des instructions return et inverser des conditions booleennes. Un score de mutation inferieur a 80% indique generalement que les tests verifient les sorties sans verifier les cas limites.
// Example: this test has high coverage but low mutation score
it('calculates shipping cost', function () {
$cost = calculateShipping(weight: 5.0, zone: 'domestic');
// Only checks that the result is numeric
expect($cost)->toBeFloat();
});
// Improved: catches mutations by asserting the exact value
it('calculates domestic shipping for 5kg package', function () {
$cost = calculateShipping(weight: 5.0, zone: 'domestic');
// Exact assertion catches operator and value mutations
expect($cost)->toBe(12.50);
});Le premier test passe meme si la logique de calcul est completement fausse, tant qu'elle retourne un float. Le second test echoue immediatement quand une mutation change la formule. Les assertions specifiques produisent des scores de mutation plus eleves.
Patterns de Tests Base de Donnees et Factories
Les model factories Laravel generent des donnees de test realistes sans construction manuelle de tableaux. Pest 5 combine aux factories produit un setup de donnees lisible et maintenable.
use App\Models\Article;
use App\Models\User;
it('publishes a draft article and updates the timestamp', function () {
$author = User::factory()->create(['role' => 'editor']);
$article = Article::factory()
->for($author, 'author')
->draft()
->create(['title' => 'Testing Best Practices']);
$this->actingAs($author)
->patchJson("/api/articles/{$article->id}/publish")
->assertOk()
->assertJsonPath('data.status', 'published');
$article->refresh();
expect($article->status)->toBe('published')
->and($article->published_at)->not->toBeNull()
->and($article->published_at->isToday())->toBeTrue();
});L'etat de factory draft() definit les valeurs par defaut pour les articles non publies. Les assertions expect() chainees avec ->and() se lisent comme du langage naturel et echouent avec des messages descriptifs.
Executez php artisan test --parallel pour executer les tests sur plusieurs processus. Laravel cree automatiquement des bases de donnees de test separees pour chaque processus, evitant les conflits de donnees. Le sharding equilibre par temps de Pest 5 distribue les tests par temps d'execution reel plutot que par nombre, garantissant que chaque shard CI finit au meme moment.
Questions d'Entretien Technique Courantes sur les Tests Laravel
Les entretiens techniques pour les postes Laravel interrogent frequemment sur les connaissances en testing. Voici les questions qui apparaissent le plus souvent, avec ce qu'une bonne reponse doit couvrir.
Quelle est la difference entre fake(), mock() et spy() dans les tests Laravel ?
Le fake() de facade remplace toute la facade par une implementation en memoire (Mail::fake, Queue::fake). mock() via Mockery definit des attentes avant l'execution et echoue si elles ne sont pas remplies. spy() enregistre les interactions et permet des assertions apres l'execution, sans definir d'attentes en amont. Le choix depend de si le test doit verifier un comportement (mock), enregistrer des interactions (spy) ou prevenir les effets de bord (fake).
En quoi RefreshDatabase differe de DatabaseTransactions ?
RefreshDatabase execute les migrations une fois et encapsule chaque test dans une transaction. DatabaseTransactions suppose que la base de donnees a deja le bon schema et encapsule seulement les tests dans des transactions. RefreshDatabase est plus sur pour les pipelines CI ou la base de donnees pourrait ne pas exister. DatabaseTransactions est plus rapide quand le schema est garanti a jour.
Quand les tests fonctionnels doivent-ils etre preferes aux tests unitaires ?
Les tests fonctionnels devraient couvrir tout code qui interagit avec la couche HTTP, la base de donnees ou les services Laravel. Les tests unitaires sont reserves aux fonctions pures et aux value objects sans dependances du framework. Dans une application Laravel typique, les tests fonctionnels sont plus nombreux que les tests unitaires dans un ratio d'environ 3:1 ou plus. Cela reflete la realite que la plupart du code Laravel est inherement integre avec le framework.
Comment le Test Impact Analysis ameliore-t-il les performances CI ?
TIA enregistre quels tests touchent quels fichiers source lors de la premiere execution. Lors des executions suivantes, Pest n'execute que les tests affectes par les fichiers modifies et rejoue les resultats en cache pour les tests inchanges. Les grandes suites qui prenaient des minutes peuvent s'executer en secondes. Le compromis : TIA necessite un driver de couverture (PCOV ou Xdebug) pour construire la carte des dependances, et la premiere execution prend plus de temps qu'une execution normale.
Comment le mutation testing ameliore-t-il la qualite des tests au-dela de la couverture de code ?
La couverture de code mesure les chemins d'execution. Un test peut atteindre 100% de couverture en appelant chaque methode sans rien affirmer de significatif. Le mutation testing modifie le code source (changement d'operateurs, suppression de returns, inversion de booleens) et verifie qu'au moins un test echoue. Les mutations survivantes revelent des assertions trop larges ou manquantes. L'execution de php artisan test --mutate produit un pourcentage de score de mutation en plus de la couverture standard.
Pour plus de questions d'entretien Laravel, la banque de questions SharpSkill couvre l'authentification, les patterns du conteneur de services, les relations Eloquent et l'architecture des queues.
Tester les Reponses HTTP et les Assertions JSON
Les helpers de test HTTP de Laravel verifient les codes de statut, les headers, les structures JSON et les cibles de redirection. Combines avec Pest, ils forment des tests d'integration concis.
use App\Models\User;
describe('API Authentication', function () {
it('rejects unauthenticated requests with 401', function () {
$this->getJson('/api/profile')
->assertUnauthorized();
});
it('returns the authenticated user profile', function () {
$user = User::factory()->create([
'name' => 'John Doe',
'email' => 'john@example.com',
]);
$this->actingAs($user)
->getJson('/api/profile')
->assertOk()
->assertJson([
'data' => [
'name' => 'John Doe',
'email' => 'john@example.com',
],
]);
});
it('validates required fields on registration', function () {
$this->postJson('/api/register', [])
->assertUnprocessable()
->assertJsonValidationErrors(['name', 'email', 'password']);
});
});Le bloc describe regroupe les tests lies a l'authentification. Chaque nom de test decrit le comportement attendu, pas l'implementation. La methode assertJsonValidationErrors verifie que des champs specifiques ont des messages d'erreur de validation.
Sources
- Pest 5 Released par Laravel News, annoncant le moteur TIA, le plugin Agent et les Evals
- Pest 5 Now Available, documentation officielle avec les prerequis et nouvelles fonctionnalites
- What We Know About Laravel 13, couvrant les PHP Attributes, AI SDK et la sortie de mars 2026
- PHPUnit 13 Release Announcement, detaillant les nouvelles assertions et deprecations
Ce qu'il faut retenir des Tests Laravel avec Pest 5
- Pest 5 avec Laravel 13 elimine le boilerplate grace a une API de configuration fluide, les chaines
expect()et la decouverte automatique des tests - Le moteur TIA ne reexecute que les tests affectes, reduisant l'execution des grandes suites de minutes a secondes sans sacrifier la precision de couverture
- Les tests fonctionnels devraient constituer le coeur d'une suite de tests Laravel, les tests unitaires etant reserves a la logique metier isolee
- Les fakes de facades (
Mail::fake(),Queue::fake()) gerent le mocking au niveau framework, tandis que Mockery gere les dependances tierces injectees via le conteneur - Les tests d'architecture imposent des regles structurelles (pas d'Eloquent dans les controleurs, pas de fonctions debug) sans cout runtime
- Le mutation testing avec
--mutatedetecte les assertions faibles que la couverture de code seule manque - Les etats de factory et les assertions chainees
expect()->and()gardent le setup de donnees de test lisible et les assertions specifiques - Pour la preparation aux entretiens Laravel, comprendre mock/fake/spy, le comportement de
RefreshDatabase, TIA et le mutation testing demontre une maturite en testing au-dela de la simple couverture
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Tu saurais repérer le bug en Laravel ?
Un vrai bout de code, un bug caché, une tentative par jour. Sans compte pour essayer.

Écrit par
Anthony Fillion-MailletFondateur de SharpSkill
Développeur fullstack depuis plus de 10 ans. Il dirige SharpSkill et répond de tout ce qui y est publié.
Mis à jour le 2 septembre 2026
Tags
Partager
Articles similaires

Solutions Laravel : Patterns Avancés, Débogage et Questions d'Entretien 2026
Maîtriser les solutions Laravel avec les patterns architecturaux avancés, les techniques de débogage et les connaissances essentielles pour les entretiens. Classes de service, pattern Repository, débogage avec Telescope et questions fréquentes.

Questions d'entretien Laravel et PHP : Top 25 en 2026
Les 25 questions d'entretien Laravel et PHP les plus posées. Eloquent ORM, middleware, artisan, queues, tests et architecture avec réponses détaillées et exemples de code.

Laravel Livewire 3 en 2026 : Applications Réactives et Questions d'Entretien
Maîtrisez Laravel Livewire 3 avec ce guide complet sur les composants réactifs, l'intégration Alpine.js, la validation en temps réel et les questions d'entretien technique.