PHPUnit affirme qu'une exception a été lancée?
est-ce que quelqu'un sait s'il y a un assert
ou quelque chose comme ça qui peut tester si une exception a été jetée dans le code testé?
12 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 () PHPUnit documentation
PHPUnit auteur de l'article fournit une explication détaillée sur le test des exceptions meilleures pratiques.
vous pouvez également utiliser un annotation docblock :
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
pour PHP 5.5+ (en particulier avec le code namespaced), je préfère maintenant utiliser ::class
si vous utilisez PHP 5.5+, vous pouvez utiliser ::class
résolution pour obtenir le nom de la classe avec expectException
/ setExpectedException
. Cela offre plusieurs avantages:
- le nom sera entièrement qualifié avec son espace de nom (le cas échéant).
- il se résout à un
string
de sorte qu'il fonctionnera avec n'importe quelle version de PHPUnit. - vous obtenez le code-completion dans votre IDE.
- le compilateur PHP émettra une erreur si vous vous trompez sur le nom de classe.
exemple:
namespace \My\Cool\Package;
class AuthTest extends \PHPUnit_Framework_TestCase
{
public function testLoginFailsForWrongPassword()
{
$this->expectException(WrongPasswordException::class);
Auth::login('Bob', 'wrong');
}
}
PHP compiles
WrongPasswordException::class
en
"\My\Cool\Package\WrongPasswordException"
sans que PHPUnit soit le plus sage.
Note : PHPUnit 5.2 introduit
expectException
comme un remplacement poursetExpectedException
.
ci-dessous permet de tester le message d'exception et le code d'exception.
Important: Ce sera un échec si attendu exception levée pas trop.
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());
}
vous pouvez utiliser assertException extension pour faire valoir plus d'une exception lors 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 code de nice..
public function testException() {
try {
$this->methodThatThrowsException();
$this->fail("Expected Exception has not been raised.");
} catch (Exception $ex) {
$this->assertEquals($ex->getMessage(), "Exception message");
}
}
une autre voie peut être la suivante:
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
veuillez vous assurer que votre classe d'essai s'étend \PHPUnit_Framework_TestCase
.
voici toutes les affirmations d'exception que vous pouvez faire. Notez que tous sont optionnel .
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!');
}
}
Documentation peut être trouvé ici .
PHPUnit actuel " meilleures pratiques , " par exception, les tests sont.. terne.
- Ne prend pas en charge plusieurs exceptions par test, ou des affirmations appelé après que l'exception est levée
- Documentation manque de robustesse ou des exemples clairs
- syntaxe Non standard et pouvant prêter à confusion ("expect "vs" assert")
- supporte uniquement les assertions pour le message, le code, et classe
- N'inverse, comme "expectNoException"
j'ai ouvert un GitHub issue pour PHPUnit et a été immédiatement rejetée par le responsable.
comme je ne suis pas du tout d'accord avec la mise en œuvre actuelle de expectException
, j'ai fait un trait à utiliser sur mes cas d'essai.
Bibliothèque
Le AssertThrows
trait est publié à Github et packagist de sorte qu'il peut être installé avec composer.
Exemple Simple
Juste pour illustrer l'esprit derrière la syntaxe:
<?php
// Within your test case...
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
plutôt soigné?
"1519280920 Complet" Exemple D'Utilisation
Voici une vraie classe de TestCase qui montre 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();
});
}
}
?>
la méthode PHPUnit expectException
est très incommode parce qu'elle ne permet de tester qu'une seule exception par méthode d'essai.
j'ai fait cette fonction d'assistant pour affirmer qu'une fonction jette 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 de cette façon:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
soyez très prudent sur "/**"
, remarquez le double"*". Écrire seulement "** " (Astérix) échouera votre code.
Assurez-vous également de votre utilisation de la dernière version de phpUnit. Dans certaines versions antérieures de phpunit @expectedException, L'Exception n'est pas supportée. J'avais 4.0 et ça ne marchait pas pour moi, j'ai dû mettre à jour à 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer à mettre à jour avec composer.
Pour PHPUnit 5.7.27 et PHP 5.6 et de tester de multiples exceptions dans un test, il était important de forcer l'exception des tests. L'utilisation de la gestion d'exception seule pour affirmer l'instance D'Exception sautera l'épreuve 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());
}