Qualcuno sa se esiste una assert
o qualcosa del genere che può verificare se nel codice in prova è stata generata un'eccezione?
Qualcuno sa se esiste una assert
o qualcosa del genere che può verificare se nel codice in prova è stata generata un'eccezione?
Risposte:
<?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);
}
}
awaException () Documentazione PHPUnit
L'articolo dell'autore PHPUnit fornisce spiegazioni dettagliate sul test delle migliori pratiche di eccezioni.
$this->setExpectedException('\My\Name\Space\MyCustomException');
setExpectedException
è deprecato, sostituito con expectException
quello. :)
expectException()
. Anche se potrebbe essere stato ovvio per alcuni, è stato un gotcha per me.
Puoi anche usare un'annotazione docblock fino al rilascio di PHPUnit 9:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
Per PHP 5.5+ (specialmente con il codice con spazio dei nomi), ora preferisco usare ::class
IncorrectPasswordException
dovrebbe essere sufficiente: il messaggio uguale "Wrong password for bob@me.com"
è secondario. Aggiungete a ciò che volete dedicare il minor tempo possibile alla scrittura dei test e inizia a vedere quanto diventano importanti i test semplici.
Se usi PHP 5.5+, puoi usare la ::class
risoluzione per ottenere il nome della classe con expectException
/setExpectedException
. Ciò offre numerosi vantaggi:
string
modo che funzionerà con qualsiasi versione di PHPUnit.Esempio:
namespace \My\Cool\Package;
class AuthTest extends \PHPUnit_Framework_TestCase
{
public function testLoginFailsForWrongPassword()
{
$this->expectException(WrongPasswordException::class);
Auth::login('Bob', 'wrong');
}
}
Compilazioni PHP
WrongPasswordException::class
in
"\My\Cool\Package\WrongPasswordException"
senza PHPUnit essere il più saggio.
Nota : PHPUnit 5.2 introdotto
expectException
in sostituzione disetExpectedException
.
Il codice seguente testerà il messaggio di eccezione e il codice di eccezione.
Importante: fallirà se non viene generata anche l'eccezione prevista.
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()
non è pensato per essere usato in questo modo non credo, almeno non attualmente (PHPUnit 3.6.11); agisce come un'eccezione stessa. Utilizzando l'esempio, se $this->fail("Expected exception not thrown")
viene chiamato, il catch
blocco viene attivato ed $e->getMessage()
è "Eccezione prevista non generata" .
fail
probabilmente appartiene dopo il blocco catch, non all'interno del tentativo.
fail
non dovrebbe essere nel try
blocco. Di per sé innesca il catch
blocco producendo risultati falsi.
catch(Exception $e)
. Questo metodo funziona abbastanza bene per me quando provo a cogliere specifiche eccezioni:try { throw new MySpecificException; $this->fail('MySpecificException not thrown'); } catch(MySpecificException $e){}
È possibile utilizzare l'estensione assertException per affermare più di un'eccezione durante un'esecuzione di test.
Inserisci il metodo nel tuo TestCase e usa:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
Ho anche fatto un tratto per gli amanti del bel codice ..
assertException
è definito. Inoltre non riesco a trovarlo nel manuale di PHPUnit.
asertException
metodo non fa parte di PHPUnit originale. È necessario ereditare la PHPUnit_Framework_TestCase
classe e aggiungere manualmente il metodo collegato in post sopra . I casi di test erediteranno quindi questa classe ereditata.
Un modo alternativo può essere il seguente:
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
Assicurati che la tua classe di test si estenda \PHPUnit_Framework_TestCase
.
Il expectException
metodo PHPUnit è molto scomodo perché consente di testare solo un'eccezione per un metodo di test.
Ho creato questa funzione di supporto per affermare che alcune funzioni generano un'eccezione:
/**
* 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');
}
Aggiungilo alla tua classe di test e chiama in questo modo:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
Le attuali " migliori pratiche " di PHPUnit per i test delle eccezioni sembrano ... poco brillanti ( documenti ).
Dal momento che volevo qualcosa di più rispetto all'attuale expectException
implementazione, ho creato un tratto da utilizzare nei miei casi di test. Sono solo ~ 50 righe di codice .
assert
Sintassi standardassertNotThrows
Throwable
errori PHP 7Ho pubblicato il AssertThrows
tratto su Github e packagist in modo che possa essere installato con il compositore.
Giusto per illustrare lo spirito dietro la sintassi:
<?php
// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);
// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
Piuttosto pulito?
Vedi sotto per un esempio di utilizzo più completo:
<?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()
è assertEquals(mixed $expected, mixed $actual...)
, al contrario come nel tuo esempio, quindi dovrebbe essere$this->assertEquals("Exception message", $ex->getMessage());
Ecco tutte le affermazioni sulle eccezioni che puoi fare. Si noti che tutti sono opzionali .
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 documentazione è disponibile qui .
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
Fai molta attenzione "/**"
, nota il doppio "*". Scrivere solo "**" (asterix) non riuscirà il tuo codice. Assicurati anche di utilizzare l'ultima versione di phpUnit. In alcune versioni precedenti di phpunit @expectedException l'eccezione non è supportata. Avevo 4.0 e non ha funzionato per me, ho dovuto aggiornare a 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer per aggiornare con il compositore.
Per PHPUnit 5.7.27 e PHP 5.6 e per testare più eccezioni in un test, era importante forzare il test delle eccezioni. L'uso della sola gestione delle eccezioni per affermare l'istanza di Exception salterà il test della situazione se non si verifica alcuna eccezione.
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>; }
}
ecco il 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 è una libreria straordinaria, ma questo punto specifico è un po 'frustrante. Questo è il motivo per cui possiamo usare la libreria open source turbotesting-php che ha un metodo di asserzione molto conveniente per aiutarci a testare le eccezioni. Si trova qui:
E per usarlo, faremmo semplicemente quanto segue:
AssertUtils::throwsException(function(){
// Some code that must throw an exception here
}, '/expected error message/');
Se il codice che digitiamo all'interno della funzione anonima non genera un'eccezione, verrà generata un'eccezione.
Se il codice che digitiamo all'interno della funzione anonima genera un'eccezione, ma il suo messaggio non corrisponde al regexp previsto, verrà generata anche un'eccezione.