Est-ce que quelqu'un sait s'il existe un assert
ou quelque chose comme ça qui peut tester si une exception a été levée dans le code testé?
Est-ce que quelqu'un sait s'il existe un assert
ou quelque chose comme ça qui peut tester si une exception a été levée dans le code testé?
Réponses:
<?php
require_once 'PHPUnit/Framework.php';
class ExceptionTest extends PHPUnit_Framework_TestCase
{
public function testException()
{
$this->expectException(InvalidArgumentException::class);
// or for PHPUnit < 5.2
// $this->setExpectedException(InvalidArgumentException::class);
//...and then add your test code that generates the exception
exampleMethod($anInvalidArgument);
}
}
expectException () documentation PHPUnit
L'article de l'auteur PHPUnit fournit des explications détaillées sur les meilleures pratiques de test des exceptions.
$this->setExpectedException('\My\Name\Space\MyCustomException');
setExpectedException
méthode est déconseillée, remplacée par celle- expectException
là. :)
expectException()
. Bien que cela ait pu être évident pour certains, c'était un piège pour moi.
Vous pouvez également utiliser une annotation docblock jusqu'à la sortie de PHPUnit 9:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
Pour PHP 5.5+ (en particulier avec le code avec espace de noms), je préfère maintenant utiliser ::class
IncorrectPasswordException
devrait être suffisant - que le message égal "Wrong password for bob@me.com"
est accessoire. Ajoutez à cela que vous voulez passer le moins de temps possible à écrire des tests, et vous commencez à voir à quel point les tests simples deviennent importants.
Si vous utilisez PHP 5.5+, vous pouvez utiliser la ::class
résolution pour obtenir le nom de la classe avec expectException
/setExpectedException
. Cela offre plusieurs avantages:
string
donc il fonctionnera avec n'importe quelle version de PHPUnit.Exemple:
namespace \My\Cool\Package;
class AuthTest extends \PHPUnit_Framework_TestCase
{
public function testLoginFailsForWrongPassword()
{
$this->expectException(WrongPasswordException::class);
Auth::login('Bob', 'wrong');
}
}
PHP compile
WrongPasswordException::class
dans
"\My\Cool\Package\WrongPasswordException"
sans PHPUnit étant le plus sage.
Remarque : PHPUnit 5.2 a été introduit
expectException
en remplacement desetExpectedException
.
Le code ci-dessous testera le message d'exception et le code d'exception.
Important: il échouera si l'exception attendue n'est pas levée également.
try{
$test->methodWhichWillThrowException();//if this method not throw exception it must be fail too.
$this->fail("Expected exception 1162011 not thrown");
}catch(MySpecificException $e){ //Not catching a generic Exception or the fail function is also catched
$this->assertEquals(1162011, $e->getCode());
$this->assertEquals("Exception Message", $e->getMessage());
}
$this->fail()
n'est pas censé être utilisé de cette façon, je ne pense pas, du moins pas actuellement (PHPUnit 3.6.11); elle fait elle-même exception. En utilisant votre exemple, si $this->fail("Expected exception not thrown")
est appelé, le catch
bloc est déclenché et $e->getMessage()
est "Exception attendue non levée" .
fail
appartient probablement après le bloc catch, pas à l'intérieur de l'essai.
fail
ne devrait pas être dans le try
bloc. Il déclenche en soi le catch
bloc produisant de faux résultats.
catch(Exception $e)
. Cette méthode fonctionne très bien pour moi lorsque j'essaie d'attraper des exceptions spécifiques:try { throw new MySpecificException; $this->fail('MySpecificException not thrown'); } catch(MySpecificException $e){}
Vous pouvez utiliser l' extension assertException pour affirmer plusieurs exceptions au cours d'une exécution de test.
Insérez la méthode dans votre TestCase et utilisez:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
J'ai aussi fait un trait pour les amateurs de joli code ..
assertException
n'est pas défini. Je ne le trouve pas non plus dans le manuel PHPUnit.
asertException
méthode ne fait pas partie de PHPUnit d'origine. Vous devez hériter la PHPUnit_Framework_TestCase
classe et ajouter manuellement la méthode liée dans le post ci-dessus . Vos cas de test hériteront alors de cette classe héritée.
Une autre manière peut être la suivante:
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
Veuillez vous assurer que votre classe de test s'étend \PHPUnit_Framework_TestCase
.
PHPUnit expectException
méthode est très gênante car elle permet de tester une seule exception par méthode de test.
J'ai créé cette fonction d'aide pour affirmer que certaines fonctions lèvent une exception:
/**
* Asserts that the given callback throws the given exception.
*
* @param string $expectClass The name of the expected exception class
* @param callable $callback A callback which should throw the exception
*/
protected function assertException(string $expectClass, callable $callback)
{
try {
$callback();
} catch (\Throwable $exception) {
$this->assertInstanceOf($expectClass, $exception, 'An invalid exception was thrown');
return;
}
$this->fail('No exception was thrown');
}
Ajoutez-le à votre classe de test et appelez ainsi:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
Les " meilleures pratiques " actuelles de PHPUnit pour les tests d'exception semblent .. terne ( docs ).
Comme je voulais plus que l' expectException
implémentation actuelle , j'ai fait un trait à utiliser sur mes cas de test. Ce ne sont que ~ 50 lignes de code .
assert
Syntaxe standardassertNotThrows
Throwable
erreurs PHP 7J'ai publié le AssertThrows
trait sur Github et packagist pour qu'il puisse être installé avec composer.
Juste pour illustrer l'esprit derrière la syntaxe:
<?php
// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);
// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
Génial?
Veuillez voir ci-dessous pour un exemple d'utilisation plus complet:
<?php
declare(strict_types=1);
use Jchook\AssertThrows\AssertThrows;
use PHPUnit\Framework\TestCase;
// These are just for illustration
use MyNamespace\MyException;
use MyNamespace\MyObject;
final class MyTest extends TestCase
{
use AssertThrows; // <--- adds the assertThrows method
public function testMyObject()
{
$obj = new MyObject();
// Test a basic exception is thrown
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
// Test custom aspects of a custom extension class
$this->assertThrows(MyException::class,
function() use ($obj) {
$obj->doSomethingBad();
},
function($exception) {
$this->assertEquals('Expected value', $exception->getCustomThing());
$this->assertEquals(123, $exception->getCode());
}
);
// Test that a specific exception is NOT thrown
$this->assertNotThrows(MyException::class, function() use ($obj) {
$obj->doSomethingGood();
});
}
}
?>
public function testException() {
try {
$this->methodThatThrowsException();
$this->fail("Expected Exception has not been raised.");
} catch (Exception $ex) {
$this->assertEquals($ex->getMessage(), "Exception message");
}
}
assertEquals()
est assertEquals(mixed $expected, mixed $actual...)
, inversée comme dans votre exemple, il devrait donc être$this->assertEquals("Exception message", $ex->getMessage());
Voici toutes les affirmations d'exception que vous pouvez faire. Notez que tous sont facultatifs .
class ExceptionTest extends PHPUnit_Framework_TestCase
{
public function testException()
{
// make your exception assertions
$this->expectException(InvalidArgumentException::class);
// if you use namespaces:
// $this->expectException('\Namespace\MyException');
$this->expectExceptionMessage('message');
$this->expectExceptionMessageRegExp('/essage$/');
$this->expectExceptionCode(123);
// code that throws an exception
throw new InvalidArgumentException('message', 123);
}
public function testAnotherException()
{
// repeat as needed
$this->expectException(Exception::class);
throw new Exception('Oh no!');
}
}
La documentation peut être trouvée ici .
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
Faites très attention "/**"
, notez le double "*". Écrire seulement "**" (astérisque) échouera votre code. Assurez-vous également que vous utilisez la dernière version de phpUnit. Dans certaines versions antérieures de phpunit, l'exception @expectedException n'est pas prise en charge. J'avais 4.0 et cela ne fonctionnait pas pour moi, j'ai dû mettre à jour vers 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer pour mettre à jour avec composer.
Pour PHPUnit 5.7.27 et PHP 5.6 et pour tester plusieurs exceptions dans un seul test, il était important de forcer le test d'exception. L'utilisation de la gestion des exceptions seule pour affirmer l'instance d'Exception sautera le test de la situation si aucune exception ne se produit.
public function testSomeFunction() {
$e=null;
$targetClassObj= new TargetClass();
try {
$targetClassObj->doSomething();
} catch ( \Exception $e ) {
}
$this->assertInstanceOf(\Exception::class,$e);
$this->assertEquals('Some message',$e->getMessage());
$e=null;
try {
$targetClassObj->doSomethingElse();
} catch ( Exception $e ) {
}
$this->assertInstanceOf(\Exception::class,$e);
$this->assertEquals('Another message',$e->getMessage());
}
function yourfunction($a,$z){
if($a<$z){ throw new <YOUR_EXCEPTION>; }
}
voici le test
class FunctionTest extends \PHPUnit_Framework_TestCase{
public function testException(){
$this->setExpectedException(<YOUR_EXCEPTION>::class);
yourfunction(1,2);//add vars that cause the exception
}
}
PhpUnit est une bibliothèque incroyable, mais ce point spécifique est un peu frustrant. C'est pourquoi nous pouvons utiliser la bibliothèque open source turbotesting-php qui a une méthode d'assertion très pratique pour nous aider à tester les exceptions. On le trouve ici:
Et pour l'utiliser, nous ferions simplement ce qui suit:
AssertUtils::throwsException(function(){
// Some code that must throw an exception here
}, '/expected error message/');
Si le code que nous tapons à l'intérieur de la fonction anonyme ne lève pas d'exception, une exception sera levée.
Si le code que nous tapons à l'intérieur de la fonction anonyme lève une exception, mais que son message ne correspond pas à l'expression rationnelle attendue, une exception sera également levée.