Aller plus loin avec les tests unitaires
Objectifs
Apprendre à tester des exceptions PHP
Contexte :
Pour aller plus loin avec l'utilisation et la maîtrise des tests unitaires au sein d'un projet Symfony, il peut être intéressant de découvrir comment tester nos exceptions PHP et utiliser correctement le système de Data Provider (ou fournisseur de données) livré avec PHPUnit.
PHPUnit offre la possibilité de tester la levée d'exceptions PHP. Ce type de test nous permettra de nous assurer que ces dernières sont correctement définies et effectivement levées en cas de problème.
Méthode :
Ce test passe toujours par l'utilisation de la classe TestCase
issue du framework PHPUnit. Plutôt que la méthode assertEquals()
, nous utiliserons ici la méthode expectException()
. Comme son nom l'indique, elle permet de s'assurer qu'une exception est bien levée en cas de mauvaise pratique.
Reprenons l'exemple de notre classe HelloWorld et ajoutons à la méthode hello()
une simple exception de type InvalidArgumentException
, se levant si l'argument reçu ne correspond pas à une chaîne de caractères.
La classe à tester
<?php
# src/Util/HelloWorld.php
namespace App\Util;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
class HelloWorld {
public function hello($name) {
if(!is_string($name)) {
throw new InvalidArgumentException("La méthode 'hello()' accepte uniquement une chaîne de caractère en entrée.");
}
return 'Hello ' . $name;
}
}
Pour tester la levée de cette exception, nous créons une nouvelle classe de test « ExceptionTest
» étendant la classe TestCase
de PHPUnit afin d'avoir accès à la méthode expectException()
.
Au sein de cette classe, nous écrivons une méthode testException()
, chargée de tester la levée de l'exception rédigée précédemment dans la classe HelloWorld
.
Pour cela, nous créons une instance de cette classe avant d'appeler la méthode expectException()
. Notez que cette dernière attend le type d'exception à tester en argument. Pour rappel, nous souhaitons, ici, tester une exception de type InvalidArgumentException
.
Nous appelons enfin la méthode où l'exception est censée être levée en prenant soin de lui donner un mauvais type d'argument. Dans notre exemple, passons un entier en argument de la méthode hello()
qui, je vous le rappelle, s'attend normalement à recevoir une chaîne de caractères.
La classe de test
<?php
# tests/Util/ExceptionTest.php
namespace Tests\Util;
use PHPUnit\Framework\TestCase;
use App\Util\HelloWorld;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
class ExceptionTest extends TestCase
{
public function testException()
{
$helloWorld = new HelloWorld();
$this->expectException(InvalidArgumentException::class);
$helloWorld->hello(1);
}
}
Alternativement, il est possible d'utiliser l'annotation @expectedException
pour alléger notre code.
La classe de test allégée
<?php
# tests/Util/ExceptionTest.php
namespace Tests\Util;
use PHPUnit\Framework\TestCase;
use App\Util\HelloWorld;
class ExceptionTest extends TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
$helloWorld = new HelloWorld();
$helloWorld->hello(1);
}
}
Syntaxe : À retenir
Concernant le test d'exceptions PHP, il est essentiel de retenir la méthode expectException()
issue de la classe TestCase
à faire étendre à notre classe de test. Souvenez-vous également que cette méthode prend le type d'exception à lever en argument.
Il est également nécessaire de provoquer volontairement la levée de l'exception au sein de la méthode de test pour valider l'assertion.
Enfin, l'annotation @expectedException
suivie par le type d'exception testé peut remplacer l'appel de la méthode expectException()
.