¿Alguien sabe si hay assert
algo o algo así que puede probar si se produjo una excepción en el código que se está probando?
¿Alguien sabe si hay assert
algo o algo así que puede probar si se produjo una excepción en el código que se está probando?
Respuestas:
<?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 () documentación de PHPUnit
El artículo del autor PHPUnit proporciona una explicación detallada sobre las mejores prácticas de excepciones de prueba.
$this->setExpectedException('\My\Name\Space\MyCustomException');
setExpectedException
está en desuso, reemplazado por el expectException
uno. :)
expectException()
. Si bien podría haber sido obvio para algunos, fue una de gotcha para mí.
También puede usar una anotación docblock hasta que se lance PHPUnit 9:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
Para PHP 5.5+ (especialmente con código de espacio de nombres), ahora prefiero usar ::class
IncorrectPasswordException
debería ser suficiente: que el mensaje sea igual "Wrong password for bob@me.com"
es auxiliar. Agregue a eso que desea pasar el menor tiempo posible escribiendo pruebas, y comenzará a ver cuán importantes se vuelven las pruebas simples.
Si está ejecutando PHP 5.5+, puede usar la ::class
resolución para obtener el nombre de la clase con expectException
/setExpectedException
. Esto proporciona varios beneficios:
string
modo que funcionará con cualquier versión de PHPUnit.Ejemplo:
namespace \My\Cool\Package;
class AuthTest extends \PHPUnit_Framework_TestCase
{
public function testLoginFailsForWrongPassword()
{
$this->expectException(WrongPasswordException::class);
Auth::login('Bob', 'wrong');
}
}
PHP compila
WrongPasswordException::class
dentro
"\My\Cool\Package\WrongPasswordException"
sin PHPUnit siendo el más sabio.
Nota : PHPUnit 5.2 se introdujo
expectException
como un reemplazo parasetExpectedException
.
El siguiente código probará el mensaje de excepción y el código de excepción.
Importante: fallará si la excepción esperada no se produce también.
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()
no está destinado a ser utilizado de esta manera, no creo, al menos no actualmente (PHPUnit 3.6.11); Actúa como una excepción en sí misma. Usando su ejemplo, si $this->fail("Expected exception not thrown")
se llama, entonces el catch
bloque se dispara y $e->getMessage()
es "Excepción esperada no lanzada" .
fail
probablemente pertenece después del bloque catch, no dentro del intento.
fail
no debe estar en el try
bloque. En sí mismo, activa el catch
bloqueo produciendo resultados falsos.
catch(Exception $e)
. Este método funciona bastante bien para mí cuando trato de capturar excepciones específicas:try { throw new MySpecificException; $this->fail('MySpecificException not thrown'); } catch(MySpecificException $e){}
Puede usar la extensión ClaimException para afirmar más de una excepción durante la ejecución de una prueba.
Inserte el método en su TestCase y use:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
También hice un rasgo para los amantes del buen código ...
assertException
está definido. Tampoco puedo encontrarlo en el manual de PHPUnit.
asertException
método no es parte de PHPUnit original. Debe heredar la PHPUnit_Framework_TestCase
clase y agregar el método vinculado en la publicación anterior manualmente. Sus casos de prueba heredarán esta clase heredada.
Una forma alternativa puede ser la siguiente:
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
Asegúrese de que su clase de prueba se extienda \PHPUnit_Framework_TestCase
.
El expectException
método PHPUnit es muy inconveniente porque permite probar solo una excepción por método de prueba.
He hecho esta función auxiliar para afirmar que alguna función arroja una excepción:
/**
* 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');
}
Agréguelo a su clase de prueba y llame de esta manera:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
Las " mejores prácticas " actuales de PHPUnit para pruebas de excepción parecen ... mediocres ( docs ).
Como quería más que la expectException
implementación actual , hice un rasgo para usar en mis casos de prueba. Son solo ~ 50 líneas de código .
assert
Sintaxis estándarassertNotThrows
Throwable
errores PHP 7Publiqué el AssertThrows
rasgo en Github y Packagist para que pueda instalarse con el compositor.
Solo para ilustrar el espíritu detrás de la sintaxis:
<?php
// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);
// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
¿Con buena pinta?
Consulte a continuación un ejemplo de uso más 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()
es assertEquals(mixed $expected, mixed $actual...)
inversa, como en su ejemplo, por lo que debería ser$this->assertEquals("Exception message", $ex->getMessage());
Aquí están todas las afirmaciones de excepción que puede hacer. Tenga en cuenta que todos ellos son opcionales .
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 documentación se puede encontrar aquí .
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
Tenga mucho cuidado "/**"
, observe el doble "*". Escribir solo "**" (asterisco) fallará su código. También asegúrese de estar usando la última versión de phpUnit. En algunas versiones anteriores de phpunit @expectedException Exception no es compatible. Tenía 4.0 y no me funcionó, tuve que actualizar a 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer para actualizar con el compositor.
Para PHPUnit 5.7.27 y PHP 5.6 y para probar varias excepciones en una prueba, era importante forzar la prueba de excepción. El uso de manejo de excepciones solo para afirmar la instancia de Excepción omitirá probar la situación si no ocurre una excepción.
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>; }
}
aqui esta la prueba
class FunctionTest extends \PHPUnit_Framework_TestCase{
public function testException(){
$this->setExpectedException(<YOUR_EXCEPTION>::class);
yourfunction(1,2);//add vars that cause the exception
}
}
PhpUnit es una biblioteca increíble, pero este punto específico es un poco frustrante. Es por eso que podemos usar la biblioteca de código abierto turbotesting-php que tiene un método de afirmación muy conveniente para ayudarnos a probar excepciones. Se encuentra aquí:
Y para usarlo, simplemente haríamos lo siguiente:
AssertUtils::throwsException(function(){
// Some code that must throw an exception here
}, '/expected error message/');
Si el código que escribimos dentro de la función anónima no produce una excepción, se generará una excepción.
Si el código que escribimos dentro de la función anónima produce una excepción, pero su mensaje no coincide con la expresión regular esperada, también se generará una excepción.